UIPanGestureRecognizer requireGestureRecognizerToFail delays UIScrollView - ios

i have a UIPanGestureRecognizer on my rootViewControllers view
that controls only 2 finger swipe ( min and max are set on 2 )
I have a couple of UITableView and UIScrollView on my rootViewControllers view.
But the 2 finger swipe should always have number 1 priority
so i put a requireGestureRecognizerToFail on my UITableView and UIScrollView's panGesture property.
this works perfectly but now when i pan my UITableView and UIScrollView, it doesn't move until i stop swiping.
Is there a solution for this?
i have added a sample project to display what the problem is: https://github.com/avalanched/UIScrollViewTest

You will need to allow the gesture recognizers to simultaneously recognize by setting the delegate on all the gesture recognizers and implementing gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:.
See Apple's UIGestureRecognizerDelegate Documentation.
You also need to remove the requireGestureRecognizerToFail calls, these are what causes the delay.

Related

UIScrollView - scroll or swipe?

In my app I have a UIScrollView and I need to swipe left and right from one picture to the next, but I also need to recognize a scroll.
How do I differentiate between a scroll and a swipe with UIScrollView?
I believe you're actually looking for is an implementation of UIScrollView with Paging, as you do not need to handle the touch events yourself, or determine if they are scrolls or swipes.
The Apple Documentation on Scroll Views and Paging Mode should help you get started
Look into the UIScrollView Delegate Methods. ScrollView can detect different types of actions drag etc or add swipeGesture directly to the scroll view
StackOverflow has questions already on this
iOS: UIScrollView detecting Swipe Gesture
Setting up UIScrollView to swipe between 3 view controllers
How to recognize swipe gesture in UIScrollView

Cannot swipe to switch UICollectionView page if you begin gesture on a cell

I have a UICollectionView that contains a single UIButton in each cell. I've discovered it's difficult to swipe between the horizontal pages because if you touch down on a cell to begin the swipe, the UIButton touch events are triggered instead of allowing the swipe gesture to occur. I do have Delays Content Touches enabled for the collection view. What can I do to solve this so that it will recognize the page pan swipe gesture when you begin swiping on a cell? Perhaps the amount of delay can be increased before it recognizes a UIControl event?
Note that I do need to preserve the touch events for the buttons - I need to know when these events occur: TouchDown, TouchDragEnter, TouchCancel, TouchDragExit, and TouchUpInside.
Without the knowledge of whether you add the gesture recognizer in storyboard or by code, I can only suggest that you can try to creates a dependency relationship between the cell's gesture recognizer and the other gesture recognizer.
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer
You have to set delaysContentTouches to YES on your UICollectionView. That way, there will be a small delay before the cells will receive a touch, and the built-in swipe recogniser can do its work.
You can also do that from the nib/storyboard by ticking the appropriate checkmark in IB:
It seems this was only a problem in iOS 8.0 (at least the simulator), as I'm no longer experiencing it in iOS 8.1.

Limit UITableView panning to 1 finger

I have a scenario where I have two UITableViews as a subview in a main UIView:
UIView (frame = full screen)
+--- UITableView (frame = ~1/3 of the screen)
+--- UITableView (frame = second ~1/3 of the screen)
I want to detect a three finger swipe up on the whole screen area (and also allow the user to pan UITableViews up and down with at least one finger).
I have a UISwipeGestureRecognizer attached to UIView with numberOfTouchesRequired = 3.
I've tried these:
Setting both internal UIPanGestureRecognizers maximumNumberOfTouches to 1 on both UITableViews. To my understanding this should prevent two and three finger pans on the UITableViews but it doesn't. (If I set enabled to NO on these UIPanGestureRecognizers, the touches are correctly passed to the superview. But then the panning/scrolling doesn't work.)
Calling panGestureRecognizer requireGestureRecognizerToFail: with my UISwipeGestureRecognizer on both UITableViews. This works partly, but the panning waits until the swipe hasn't been completed and it feels very clumsy.
Overriding UITableView with setting shouldRecognizeSimultaneouslyWithGestureRecognizer: to return YES, which allows me to detect the three finger swipe. However, the UITableViews beneath pan/scroll up unintentionally.
So how do I limit the number of panning touches to 1 (or 2) and let the three-finger UISwipeGestureRecognizer recognize three finger swipes?
Try overriding canPreventGestureRecognizer: on the top (whole screen) UIPanGestureRecognizer, returning NO for each of the two table view gesture recognizers.
I'd also try overriding canBePreventedByGestureRecognizer: on each of the two table view gesture recognizers to return NO in the case of the topmost UIPanGestureRecognizer.
I've run into a similar situation as yourself quite a while ago and can't remember how I fixed it (the project is long gone), but I seem to remember playing around with the aforementioned methods and eventually getting it to work.

How do I pass delayed scroll gestures from a UIButton inside of a UIScrollView?

I have a UIScrollView that contains several UIButtons. Each button is wired up to take an action when the user inputs a touch up event, so they are able to place their finger on the button and it will not be selected until it is raised. Currently, if I made a swipe gesture to scroll the UIScrollView quickly, then the scroll view moves as expected even if the gesture happens directly over a UIButton. HOWEVER, if I hold my finger down too long on a UIButton (about 1 second), the UIScrollView will no longer recognize the gesture and will not be able to scroll until the finger is lifted up.
I am wondering if their is a way to always have the UIScrollView recognize the scroll gesture? Note that this is not an issue if I touch the UiScrollView in a location without a UIButton - it then scrolls as expected.
It may worth a try to let your UIButton respond to UIControlEventTouchDown (maybe with an empty action). I'm not sure if this will work, but conceptually I think it should let the UIButton capture the touch immediately.
(Also make sure you don't enable delaysContentTouches on your scrollview.)
I found the answer to this here: UIScrollview with UIButtons - how to recreate springboard?
Essentially, I had to extend UIScrollView and override touchesShouldCancelInContentView, having it always return YES.

UIScrollView zoomed won't produce swipe

I have a UIScrollView with zooming enabled, and a swipe gesture recognizer setup. When the user is not zoomed, the swipes come through great, but as soon as the user zooms in, the swipe won't come through.
My swipe recognizer is applied to the imageview, and I have tried to apply it to the scroller also. When zoomed, no go.
Is there a secret to getting the swipe while zoomed?
Thanks in advance!
Rob
Where is your swipe gesture recognizer?
Have you tried setting scrollView setCanCancelContentTouches:NO?
Is there a secret to getting the swipe
while zoomed?
Yes, there is. Each UIImageView should be inside its own UIScrollView which in turn are inside of main UIScrollView. No gesture recognizers are needed, just set UIScrollViews options like zoom scales etc and implement UIScrollViewDelegate methods for master UIScrollView.

Resources