Intercepting pan gestures over a UIScrollView breaks scrolling

41,851

Solution 1

OK, I figured it out. I needed to do 2 things to make this work:

1) Attach my own pan recognizer to the scroll view itself, not to another view on top of it.

2) This UIGestureRecognizerDelegate method prevents the goofy behavior that happens when both the default scrollview and my own one are invoked simultaneously.

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

Solution 2

I had the same problem to solve and I did this:

1) Attach my own pan recognizer to the scroll view.

2) Return YES on: – gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:

This will allow both gestures to work. So what that means is that on vertical scroll, both your panGesture delegate and scrollView Delegate will be fired. If it is a horizontal scroll, it will only call your panGesture delegate.

3) in my panGesture delegate, detect if it is a horizontal scroll, if it is not, ignore.

Solution 3

Swift answer:

let scrollViewPanGesture = UIPanGestureRecognizer(target: self, action: #selector(onPan(_:)))
scrollViewPanGesture.delegate = self
scrollView.addGestureRecognizer(scrollViewPanGesture)

extension ViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}
Share:
41,851

Related videos on Youtube

TotoroTotoro
Author by

TotoroTotoro

Updated on July 17, 2020

Comments

  • TotoroTotoro
    TotoroTotoro almost 4 years

    I have a vertically-scrolling UIScrollView. I want to also handle horizontal pans on it, while allowing the default vertical scroll behavior. I've put a transparent UIView over the scroll view, and added a pan gesture recognizer to it. This way I can get the pans just fine, but then the scroll view doesn't receive any gestures.

    I've implemented the following UIPanGestureRecognizerDelegate methods, hoping to limit my gesture recognizer to horizontal pans only, but that didn't help:

    - (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer {
        // Only accept horizontal pans here.
        // Leave the vertical pans for scrolling the content.
        CGPoint translation = [gestureRecognizer translationInView:self.view];
        BOOL isHorizontalPan = (fabsf(translation.x) > fabsf(translation.y));
        return  isHorizontalPan;
    }
    
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return (otherGestureRecognizer == _scrollView.panGestureRecognizer);
    }
    
    • Mick MacCallum
      Mick MacCallum over 11 years
      Have you tried [panGesture setCancelsTouchesInView:NO];? Simply returning YES in shouldRecognizeSimultaneouslyWithGestureRecognizer might help you figure out where the problem is as well.
    • TotoroTotoro
      TotoroTotoro over 11 years
      Just tried it, no difference.
  • Gagan Singh
    Gagan Singh over 10 years
    the default behavior of shouldRecognizeSimultaneouslyWithGestureRecognizer is to return NO, so that add is unneeded
  • TotoroTotoro
    TotoroTotoro over 10 years
    This is exactly the same that I recommend in my own answer.
  • P.L.
    P.L. about 10 years
    change the return value to YES and it works great.
  • Radu Simionescu
    Radu Simionescu about 10 years
    @BlackRider it is not. This returns YES
  • atulkhatri
    atulkhatri over 6 years
    Thanks gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRe‌​cognizer did the trick.