Limit UITableView panning to 1 finger - ios

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.

Related

Can't transition from UIScrollView to UIPanGesture in one movement

What I want to achieve: http://youtu.be/SUWxVtpc0JA
What I can achieve: http://youtu.be/b1xH6Xsvxcg
I’m trying to do the same vertical parallax scrolling effect that the Year Walk Companion app does when you change from text page to menu.
I’ve been able to do this effect on UIScrollViews that only move horizontally, by using a UIPanGestureRecognizer to move up and down, (imagine swiping between nested arrays). However when I have a UIScrollView with the vertical scrolling it breaks.
When I scroll down the UIScrollView it moves as you would expect, same if you move up. However the issues start when I want the UIPanGestureRecognizer to come in and move the UIScrollView itself vertically, not it’s content. To do this so far I have subclassed UIScrollView to make a test on the function gestureRecognizerShouldBegin :
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
UIPanGestureRecognizer* pan = (UIPanGestureRecognizer*)gestureRecognizer;
CGPoint panGestureTranslation = [pan translationInView:self];
if (self.contentOffset.y == 0 && panGestureTranslation.y > 0 ) {
return NO;
}
return YES;
}
It returns NO when my UIScrollView is at the top, and allows my other UIPanGesture for the parallax scrolling between pages to start again.
My problem is, when my UIScrollView is scrolling and reached the top, the function gestureRecognizerShouldBegin will not be called and force me to release the touch before allowing the UIPanGestureRecognizer to parallax scroll.
The question: How can I stop the handle of the touch by the UIScrollView and let the UIPanGestureRecognizer get the touch going up without release my finger from the screen? (like in the Year Walk Companion app).
gestureRecognizerShouldBegin isn't called because a new touch 'session' hasn't started. The existing one is still in progress and the gesture said it didn't want to start.
You could create your own gesture subclass which stays possible and only starts when the content offset < 0. Or you could use the scroll view delegate methods as your input and not use gestures at all.

UIPanGestureRecognizer requireGestureRecognizerToFail delays UIScrollView

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.

Cancel UIGestureRecognizer if subview contains gesture?

I was originally using the UITouch methods (touchesMoved: withEvent:) in order to detect the movement in a view. Due to the fact that it seemed not to update often enough I switched to using a UIPanGestureRecognizer (though this didn't actually fix the initial problem).
After using this the touches received for movements responded no matter what it was touching (different subviews) which I actually prefer. However now I have an issue with all the subviews which have movement. I need the gesture recognizer to still move the view even while touching subviews, however if the subview also moves in this direction (left/right) I need my recognizer to cancel.
It seems like gestureRecognizerShouldBegin: might be somewhere to start, but in my case, I cannot account for all subviews.
Is it possible to make pan gesture recognizer cancel if the subview (i.e. another pan recognizer, UISlider, horizontal scrollview, etc.) touched needs to be moved in left/right directions without having to account for each subview individually?

Disable scroll in UIScrollView while multi touching

In my program I use two fingers to pinch (zoom in and out), so sometimes when I want to pinch, app scrolls.
I would like to don't let scrolling in UIScrollView while two or more touches are on screen. How can I achieve that?
Try using UIGestureRecognizer.
In you case you must use a UITapGestureRecognizer, with 2 finger and one tap.
Attach the gesture on the table view.

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.

Resources