Prevent UIScrollView's UIPanGestureRecognizer from blocking UIScreenEdgePanGestureRecognizer

10,809

Solution 1

Unfortunately, creating this behavior can be a real P*** i* t** A**.

Fortunately, creating this behavior is possible using the UIGestureRecognizer Delegate even if you can't access one GestureRecognizer directly.

-(BOOL)gestureRecognizer:shouldRequireFailureOfGestureRecognizer:
-(BOOL)gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
-(BOOL)gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer: 

The second parameter ('otherGestureRecognizer') passed in the delegate methods holds the UIScrollView's PanGestureRecognizer (or private Apple - subclasses) when your gestureRecognizer 'collides' with the scrollView's.

So simply set your UIScreenEdgePanGestureRecognizer's delegate to reply to the delegate methods.

The naming of these two methods is very suboptimal and to be honest, i don't really know what the correct return values for your case are.

I just had this problem yesterday and i solved it by brutal trial & error.

Im my case, returning NO from both shouldRequireToFail and shouldBeRequiredToFail methods and YES from the simultaneous-method solved my problem.

Note: Returning NO from both methods changed the behavior compared to not 
even implementing the methods at all. Even though the documentation says 
the default return value is NO.

However, ANY GestureRecognizer behavior can be achieved by using the delegate methods. But as i said above, the naming of the methods is just very confusing. + there is as much as NO useful documentation for these methods.

Solution 2

This can be done without having to set the screen pan gesture's delegate to your view controller.

[scrollView.panGestureRecognizer requireGestureRecognizerToFail:screenPanGesture];
Share:
10,809

Related videos on Youtube

Tyler Cloutier
Author by

Tyler Cloutier

Updated on June 04, 2022

Comments

  • Tyler Cloutier
    Tyler Cloutier almost 2 years

    I have a UIScrollView that fills the screen on one page of my app, but I want to allow the user to pan from the edge of the screen to reveal a view behind it. The problem is that the UIScrollView steals the touches from my UIScreenEdgePanGestureRecognizer at the edge of the screen. Unfortunately, I can't access the UIScreenEdgePanGestureRecognizer from the view controller that has the UIScrollView (and vice-versa), so I am not able to use the method requireGestureRecognizerToFail: because I cannot able to specify which gesture recognizer should be allowed to fail. The view controller with the scroll view is a child view controller of a container view controller that has the screen edge pan gesture recognizer attached to one of the container view controller's own views.

    I'm also unable to use the delegate method

    -(BOOL)gestureRecognizer:shouldRequireFailureOfGestureRecognizer:
    

    because the UIScrollView won't allow me to set my view controller as the delegate of the scroll view's UIPanGestureRecognizer.

    How can I prevent the scrollview from stealing the edge pan touches from my own gesture recognizer?

  • Tyler Cloutier
    Tyler Cloutier about 10 years
    I agree, this API kind of forces the solution to be jenky. What I ended up doing is implementing -(BOOL)gestureRecognizer:shouldRecognizeSimultaneouslyWithGe‌​stureRecognizer: and calling [otherGestureRecognizer requireGestureRecognizerToFail:gestureRecognizer]; before returning YES. Not sure if this is good practice, but it works. I did not find that returning NO from both of those methods changed the behavior though. You may want to check that that is actually happening.
  • CodingMeSwiftly
    CodingMeSwiftly about 10 years
    Maybe returning NO from both methods changed the behavior in my case, because i have 3 different gestureRecognizer interacting and each of them is implementing the delegate methods. Maybe i should change my gestureRecognizer design, but it's working for me at the moment so i'll leave everything in place :)
  • daihovey
    daihovey over 9 years
    @TylerCloutier That's the only solution that worked for me. Thanks.
  • Ge Liu
    Ge Liu about 9 years
    I implemented (BOOL)gestureRecognizer:shouldBeRequiredToFailByGestureRecog‌​nizer: , returning YES for gestureRecognizers that collide with this one. And it worked as expected. BTW the naming of these delegate methods is indeed very confusing. Thanks.
  • Tom van Zummeren
    Tom van Zummeren almost 6 years
    This still works, almost 3 years later. This should be the accepted answer.