I'm having trouble adding a long press gesture to my UITableView. Well, technically, I do have a long press gesture recognizer, but I set the minimum taps duration to 0.08. I did this because I want to have the same general action for tapping and holding down a cell, but the action only changes based on how long the cell was held. Anyway, here is the code where I add the gesture recognizer (in viewDidLoad) :
var longPress:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
longPress.minimumPressDuration = 0.08
longPress.delegate = self
longPress.cancelsTouchesInView = false
self.tableView.addGestureRecognizer(longPress)
self.tableView.panGestureRecognizer.requireGestureRecognizerToFail(longPress)
In my handleLongPress() function, I get the CGPoint where there was a long press and then get the tableView cell from that.
So basically, if I scroll quickly, (like if I flick the screen), the table view scrolls fine. If I try to scroll slowly, the long press event fires and I can't scroll.
All I want to do is to be able to scroll slowly, I want the tableviews default scroll gesture to override any long press.
Thanks!
ScrollViews have a panGestureRecognizer property, you can call requireGestureRecognizerToFail on your long press recognizer with the scrollView's panGestureRecognizer as an argument and it will only fire if the pan gesture in the scroll view fails.
This category might solve your problem:
#interface UITableView (CellSwipeAdditions)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
#end
#implementation UITableView (CellSwipeAdditions)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
#end
Related
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.
I have added UIPanGestureRecognizer on the view of my UIViewController.
In this view (a calculator) are some UIButton triggered by the event .TouchUpInside.
The problem comes if I tap on the button and make a small pan at the same time (which might happen if you tap quickly a button and are moving to the next one at the same time). Then the pan gesture is triggered. I would like to avoid it when there is a tap on a button. But I would like to allow it if the tap takes too long (let say 0.3s is enough to trigger the pan gesture).
How can I achieve that?
Set the property cancelsTouchesInView of your gesture recognizer to NO.
Then your button should work properly.
You can use the delegate method like this-
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([touch.view isKindOfClass:[UIButton class]]) {
return NO;
}
return YES;
}
There is a dirty solution. You can just grab it in a UIScrollView
I have a table view with a pan gesture on it. When I start panning the tableview up and down the tableView selection gets disable and I can't select tableview cells.
UIPanGesture* tablePanGesture =[[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(gestureHandler:)];
tablePanGesture.delegate = self;
[tableView addGestureRecognizer:tablePanGesture];
[tablePanGesture setCancelsTouchesInView:NO];
And I using the following delegate to let my gestures and tableview gestures work together:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
I have implemented the method for table view didSelectRowAtIndexPath but when I use panning it is not called.
Is there any conflict between pan gesture and tableview Delegate?
You are missing this line:-
[tablePanGesture setCancelsTouchesInView:NO];
This will let the UIPanGesture recognize the pan gesture and also pass the touch to the next responder means your table view select or tap.
I setup a UITapGestureRecognizer on a UIScrollView in the storyboard. The Scroll View contains other contents (two UIView, one UIWebView).
The Gesture Recognizer properties are as follows:
Action: dismissPopover
delegate: postViewController
gestureRecognizers: Scroll View
state: enabled
numberOfTapsRequired: 1
numberOfTouchesRequired: 1
cancelTouchesInView: YES
delayTouchesBegan: NO
delayTouchesEnded: YES
The Scroll View (relevant) properties are as follows:
userInteractionEnabled: YES
canCancelContentTouches: YES
However, when I tap anywhere on the Scroll View, the gesture does not work.
The delegate class (conforming to UIGestureRecognizerDelegate) must implement
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
This way, the tap gesture will work.
The scroll view has it's own gesture recognizer.
You'll need to override that gesture recognizer or disable that first.
Then and then only, your gesture recognizer will work.
The better way to do this is to use the tap gesture inside the scroll view rather than adding your gesture recognizer.
I have two subviews view1 and view2. I have added LongPress and Pan gesture to my parentview.
When I longPress on view1, I will present a draggableview with popup animation just below the fingure and will continue dragging dragView to view2.
In this process panGesture selector is not called but Longpress gesture selector is called.
After i remove the fingure from dragview and then start dragging again then the panGesture selector is called.
What I need is, once the dragview is created, disable(not permanently but until pan gesture state ended is called) the longpress gesture and the pan gesture selector should be called
You have a delegate method called:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Take a look at it, you need to return YES.