UIGestureRecognizer handle touches in UITableView - uitableview

I have an UITableView in my class with a custom UITableViewCell with an UIImageView inside.
I need to detect the touch on this UIImageView to handle a custom method(handleSingleTouch:)
and I need to call the -didSelectRowAtIndexPath when the cell is selected.
So i added a UIGestureRecognizer to my TableView in this way:
UIGestureRecognizer *GEST=[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTouch:)];
[self.myTable addGestureRecognizer:GEST];
GEST.delegate=self;
[GEST release];
[GEST setCancelsTouchesInView:NO];
[GEST setDelaysTouchesEnded:NO];
There is the conflict:
every time the UIImageView is touched the tableview the GestureRecognizer start the method but also the didSelectRowAtIndexPath is called.
Someone know the way to call the gestureRecognizerMethod without call the didSelectRowAtIndexPath?

Try adding the gesture recognizer to the image rather than the table. See this answer https://stackoverflow.com/a/7760402

I can't think of a way to do that, as you need to be touch responsive in the whole cell. But what you can do is tag your UIImageView and then check at the beginning of -didSelectRowAtIndexPath, for that UIImageView and return.

Related

UICollectionView within UIScrollView: Long Press

I have added a UILongPressGestureRecognizer to my UICollectionView that is within a subclass of UIScrollView. (The UIScrollView is paged so there are 3 horizontally stacked UIViewControllers).
My code to add the UILongPressGestureRecognizer:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
longPress.delegate = self;
longPress.minimumPressDuration = 0.5;
longPress.delaysTouchesBegan = YES;
[self.collectionView addGestureRecognizer:longPress];
And an NSLog in my handleLongPress: method. Currently I hold down on a UICollectionViewCell, it highlights, but the long press is not activated. I believe my UIScrollView subclass is consuming the long press and not passing along to the UICollectionView. When I lift my finger, the didSelectItemAtIndexPath: method is called.
In my UIScrollView subclass, the only customization I have is the following:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(nonnull UIGestureRecognizer *)otherGestureRecognizer {
// This line enables the swipe to delete in the Messaging VC.
return ([otherGestureRecognizer.view.superview isKindOfClass:[UITableView class]]);
}
This was done to enable cell swiping in my UITableView, which is one of the pages of my UIScrollView. The swiping works no problem, and I have tried a number of similar checks for UICollectionView and UICollectionViewCell here but have not gotten the long press to register yet. Any advice appreciated.
Edit: I have added the long press on another UICollectionView and it is functional, but the cell never shows highlighted/selected status. I guess that is a clue as to why I can't get this long press gesture to fire.
My issue was that I was adding the gesture recognizer in the -init method. That did not work. Simply moving the code to -viewDidLoad fixed the problem.

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];

Why a UIButton on UITableViewCell only drawn darker when touch gesture continued for a short time

Pressing the button quickly and not holding for a short time, will not highlight the button.
Different from a UIButton on a common UIView.
Like the head photo in official Twitter client got same issue.
Instagram client seems solved this, all buttons works fine.
Find same question here:
Why doesn't UIButton showsTouchWhenHighlighted work when the button is on a UITableViewCell?
But I still don't know how to fix it.
Well... a UITableView is a subclass of UIScrollView and the UIScrollView class is known to eat touches for it's own purpose.
When it realizes the touch was not meant for it, it passes it to it's immediate subview.
This feature is the delaysContentTouches property (which by default is YES).
Which is why, the UIButton shows it's highlighted state only after a extended touch because the touch event was with the UITableView for a short while until it determined whether the touch was meant for scrolling or swiping the cell and on realizing the touch was for neither, it immediately passes the touch event to the subView directly below it.
In case of a quick-tap, the button's highlighted state is bypassed due to this delay and the target selector method is called directly.
To show the highlighted state of the button in a UITableView (just as it would on a UIView) do:
For iOS7+:
In -viewDidLoad or anywhere appropriate do:
[yourTableViewObject setDelaysContentTouches:NO];
Also... The cell.subviews has a class UITableViewCellScrollView which apparently is another scrollView and we need to disable the delaysContentTouches property of this class as well.
So... in the -cellForRowAtIndexPath: method (just before return cell;) do:
NSArray *test = cell.subviews;
for (UIView *currentView in cell.subviews) {
if ([NSStringFromClass([currentView class]) isEqualToString:#"UITableViewCellScrollView"]) {
UIScrollView *svTemp = (UIScrollView *) currentView;
[svTemp setDelaysContentTouches:NO];
break;
}
}
For iOS 6-:
In iOS6, the cell.subviews has a UITableViewCellContentView class which is not a scrollView subclass and so all it takes is setting one parameter for the tableView alone.
So, in -viewDidLoad or anywhere appropriate, this is all that you need:
[yourTableViewObject setDelaysContentTouches:NO];
PS: By doing this, it will mess up with the scrolling of the tableView so use your better judgement.

UITableViewCell subview does not receive touch

My reusable cell contains a view with all its informations (UIImageView, UILabel, etc.) with a frame of 0,0,320,63, named mainView
I also have another subview, added programmatically, with a frame of -160,0,160,63, named leftView, contained in mainView.
I added a UISwipeGestureRecognizer to the cell, so when you swipe, I change the frame of mainView to 160,0,320,63. It works perfectly.
I just have a problem, in leftView, I have some UIImageView with userInteractionEnabled set to YES, with a gesture recognizer on it. But this gesture recognizer is never fired, it still calls the -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath method.
I looked at this SO answer, but it does not help me.
Would somebody help me with that ?
Thank you !!
EDIT : Here is my gesture recognizer instantiation
// Selector is valid, I checked it out. _viewController too.
UIImageView * imageView = [[UIImageView alloc] initWithFrame:frame];
[imageView setImage:someImage];
[imageView setUserInteractionEnabled:YES];
[_leftView addSubview:imageView];
UITapGestureRecognizer * gr = [[UITapGestureRecognizer alloc] initWithTarget:_viewController action:selector];
[imageView addGestureRecognizer:gr];
Without seeing the gestureRecognizer's initialization, it could be a number of things that are the problem. Two main things to look into however:
1.) Have you set the cancelsTouchesInView flag? Normally this would be messing with your tableView touches, but you should look into it though.
2.) Have you verified the subview layout inside of storyboard? Is there something blocking part of your imageView?
-Also you've actually allocated the gestureRecognizer correct?
Have you tried to set table cell selectable to No? in this case your swipe gesture should still work, but table deligate method for cell selection shouldn't.
I figured it out myself.
The problem was because the leftView frame was outside of the mainView frame (-160 in x).
To solve my problem, I changed mainView in storyboard, so that it also starts at -160. And instead of adding leftView at -160 in x, I add it at 0.
Thanks anyway !

UITableView didSelectRowAtIndexPath Not Selected on UIPageViewController

I have a UIViewController that has UIPageViewController's view added to it. That UIPageViewController has a page with a subview that has a UITableView added as a subview. I am using iOS 6 and the method didSelectRowAtIndexPath is not being called when I click on the cell. There is a weird "bug" though... If I turn the page halfway and then come back to the page I was on (without completing the page turn), I'm then able to select the cell. I assume this has something to do with gesture recognizers, but I can't figure it out. I tried removing the gesture recognizers from the instantiation of the UIPageViewController, but was unable to get that to work.
I remove the tap gesture recognizers from the UIPageViewController like so, but still the buggy behavior exists...
for (UIGestureRecognizer *recognizer in pageViewController.gestureRecognizers) {
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
recognizer.enabled = NO;
}
}
Any suggestions?
Subclass UIView with UITableView. let say myUIView.
Implement the UITableView delegates in myUIView.
Add myUIView as a subview of UIPageControl.
UITableView delegates in myUIView will trigger.
It turned out to be something very simple. On my UIViewController I had the autoresizingMask set to FlexibleHeight. Changing it to None for some reason fixed my problem.
// self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
// Changed to :
self.contentView.autoresizingMask = UIViewAutoresizingNone;
If anyone can shed some light onto the reasons why this is the case, I'd appreciate it.

Resources