UICollectionViewCell subview receive tap insted - ios

I have a UICollectionViewCell with some my content on it as image, labels, views.
I would like to obtain this behavior (like an opposite behavior of a normal cell):
this cell by default have a view (a simple UIView with an alpha set to show some opacity) like when it is not selected.
when a user select the cell this alpha view have to be removed.
If I try to install a UITapRecognizer:
// Create gesture recognizer
UITapGestureRecognizer *oneTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onShadowLayerPressed)];
// Set required taps and number of touches
[oneTap setNumberOfTapsRequired:1];
[oneTap setNumberOfTouchesRequired:1];
// Add the gesture to the view
[self.shadowView addGestureRecognizer:oneTap];
and after the method
- (void)onShadowLayerPressed
{
[super setSelected:YES];
[self setSelected:YES];
}
The tap is received from the self.shadowView but it doesn't send to the cell....
How can I solve this issue?
Thanks

You are using #property (nonatomic, getter=isSelected) BOOL selected and according to the docs,
You typically do not set the value of this property directly. Changing the value of this property programmatically does not change the appearance of the cell. The preferred way to select the cell and highlight it is to use the selection methods of the collection view object.
So you are supposed to use:
- (void)selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition
Which is documented here.

Related

Two clickable items in UITableView

I have a UITableview as a contact list in which there are a lot of users. It has a thumbnail photo and profile details on each row. I want to make it like when clicking on thumbnail, it goes another page for photo and when clicking on the rest of the space it goes to somewhere else. By using table view delegate I know which row is clicked and pass data, like user id to a new ViewController. But can I know which row when the thumbnail is clicked?
I am using the tag to find the view from cell, like
UIImageView *thumbnailView = (UIImageView *) [cell viewWithTag:1];
I think I cannot label the row index by tag.
You can add gesture to thumbnail image and get events on it. Need to set tag for thumb image as per indexPath.row.
Add following code in you in cell datasource method (cellForRowIndexPath:) :
cell.YOURIMGVIEW.userInteractionEnabled = YES;
cell.YOURIMGVIEW.tag = indexPath.row;
UITapGestureRecognizer *clickable = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageClicked:)];
clickable.numberOfTapsRequired = 1;
[cell.YOURIMGVIEW addGestureRecognizer:clickable];
[clickable release];
And also used below method :
-(void)imageClicked:(id)sender
{
UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
NSLog(#"image tag is = %d", gesture.view.tag);
////////
You custome come goes Here !!!!!!!!!!!!!!
///////
}
You can use the photo as accessory view. Or use a UIButton with the photograph as background and set the action accordingly. (e.g. call a method on the view controller which then performs the push or segue. Doing so you will have to pass some data to the view controller indicating which row was actually clicked in. The number of the row can be used or you can set the tag of the button with some numeric id.)
Go the Easy way because doing it hard-way won't grant you a president award, right ?
Instead of UIImageView take a UIButton and set the Image on UIButton instance.
Set Button tag as the indexPath.row so that when you retrieve it you know which row is clicked. You can also sort it the other way but it seems quiet handy.
Add target into the button to a custom function. [ btnObj addTarget ...... ]
tyepcast you sender to a UIButton and receive the tag (indexpath.row)
You can remove all gesture recognizers and buttons in tableviewcell, and in your controller, you can implement below delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
To make this method triggered, you need to set tableview delegate as your controller, either via code as below, or using storyboard.
- (void)viewDidLoad {
self.tableview.delegate = self;
}
By doing this, it won't matter which item you clicked in your cell, delegate method will be called always.
I hope this helps.

How do I make a UILabel *not* pass touches to the UITableViewCell it's embedded in?

I have a UITableView with a bunch of cells, and I add a UILabel to each. I want the UILabel, when tapped, to accept the touches, not the cell. Obviously if they tap outside of the label and still on the cell that is fine, but if it's on the label the cell should not cause a segue or action or whatever, only the label's action on tap should fire.
My normal method to cause this is to set the UIView's userInteractionEnabled to YES, but in this case when I set it on the label it doesn't cause anything different to happen. When I watch touchesBegan in the label subclass those methods do fire, but the cell selection does as well.
How do I make the UILabel not pass the touches on to the cell?
I recommend adding a UITapGestureRecognizer to the label and setting cancelsTouchesInView property to YES to prevent the touches from being delivered to the view upon gesture recognition, ex:
UITapGestureRecognizer *labelTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:nil];
labelTapGesture.cancelsTouchesInView = YES;
[label addGestureRecognizer:labelTapGesture];
label.userInteractionEnabled = YES;
And since you don't want the gesture to perform an action, you can set its action to nil.

Gesture for specific element in custom table view cell

I'm using a custom table where every cell holds several elements, one of them is a favourite "star" icon.
I want to add a tap gesture so when the star icon is tapped it would change to "unfavourite" icon (and vice versa).
I've tried to add a tap gesture in cellForRowAtIndexPath with:
UITapGestureRecognizer *tapRecognizer;
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(favTapped)];
[[cell.contentView viewWithTag:1] addGestureRecognizer:tapRecognizer];
But tapping the icon would just call didSelectRowAtIndexPath (obviously).
My selector "favTapped" won't be called.
Any idea how to do it?
Thanks!
you need to add the
GestureRecognizer as property to your custom cell class.
in your customCell.h:
' #property (weak, nonatomic ) UIButton *yourButton; // or swipeGesture'
in tableView:cellForRowAtIndexPatch:
[cell.yourButton addTarget:self action:#selector(yourMethod) forControlEvents:yourControlEvent]; // also aviable for gestures
also verify if User interaction is enabled (in your interface builder, you can also override this in your own class or). the most simple way to do this is to write in tableView:cellForRowAtIndexPatch:
[cell.contentView setUserInteractionEnabled:YES];

Hide UITableView on touches outside the tableview

I have a small UITableView that is hidden when the view is loaded. When i click on "SHOW" UIButton, the UITableView is made visible by myTableView.hidden=NO;
I want to hide UITableView when a user touches outside its frame. Thanks for any help!
Best Approach
Simple.Before show up the UITable View add one more grayed out/Transparent view then add tap gesture recogniser on it to hide it . That's it.
Show Overlay View first - alpha will be 0.5f and background color should be clear color.
show the table view.
NOTE: over lay view should have tap recogniser which will hide the overlay and table view
in View did load
UITapGestureRecognizer *tapRecog = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(overlayDidTap:)];
[myOverLayView addGestureRecognizer:tapRecog];
- (void)overlayDidTap:(UITapGestureRecognizer *)gesture
{
//hide both overlay and table view here
}
Bad Approach
We should not add tap recogniser on main view itself. Because it may have lots of
controls inside of it. so when user tap on it. it will perform its operation. So to avoid
it we can simulate the same behaviour by above approach
You can get touch position by this:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGestureCaptured:)];
[self.view addGestureRecognizer:singleTap];
- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
CGPoint touchPoint=[gesture locationInView:self.View];
}
Then just check if the point is in tableview frame. If not then hide the tableview. Hope this help. :)
Subclass UITableView, override pointInside:withEvent:. It is templated for this reason.
Something like:
-(BOOL)pointInside:(CGPoint) point withEvent:(UIEvent*) event
{
BOOL pointIsInsideTableView = [super pointInside:point withEvent:event];
BOOL pointIsOutsideTableView = // Some test
return pointIsInsideTableView || pointIsOutsideTableView;
}
So you can catch the touch in table view implementation, where it belongs logically in this case.

Removing UIImageView if the user taps on any point outside the UIImageView

My app shows an UIView which contains four UIButtons, one of them removes the UIView, but I also need is to remove the UIView, including all containing buttons when the user taps outside it.
This is how I remove the UIView using a button action:
-(IBAction)closeSideTasks: (id)sender
{
UIView * backgroundView = (UIView *)[self.view viewWithTag:7];
[backgroundView removeFromSuperview];
}
Any help or advice is welcome.
MORE INFORMATION:
This is the scenario: there is a table view. If the user swipes from left to right on a row, then the UIView appears on the right side of the view. The UIView *newView is removed after tapping on each of the buttons inside it and executing each button action. But may be the user does not tap on any of the buttons, and the UIView remains on the view. Then, what I want to achieve is a way that the UIView *newView gets removed if the user taps anywhere outside it, to prevent that it remains always on the view...
Check out UITapGestureRecognizer.
Example:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] init];
tapGesture.delegate = self;
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
[tapGesture addTarget:self action:#selector(tapChangeImage)];
[self.profileImageView addGestureRecognizer:tapGesture];
Now add the action method:
#pragma tap gestures
-(void)tapChangeImage{
// Remove view from superview!
}
Put a large button, full screen, with no graphics, no text, and a clear background. Have its action also remove the background

Resources