3
votes

I have the following hierarchy:

  • View
    • Subview

Each of those views has UIPanGestureRecognizer assigned. Outer pan gesture recognizer is only interested in vertical panning, so I have the delegate method implemented for that:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
    CGPoint velocity = [panGestureRecognizer velocityInView:panGestureRecognizer.view];
    return fabs(velocity.y) > fabs(velocity.x);
}

However Subview's pan gesture always takes precedence in recognition. Is there any way to make outer pan gesture recognizer to recognize first and then if it fails, pan gesture from subview can take over?

I tried simultaneous recognition and it works, but then both recognizers start panning:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 

    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return YES;
    }
2

2 Answers

3
votes

Since iOS 7, UIGestureRecognizerDelegate Protocol has already declared two delegate methods for your need, you can either use |gestureRecognizer:shouldRequireFailureOfGestureRecognizer:| or |gestureRecognizerShouldBegin:shouldBeRequiredToFailByGestureRecognizer:| but in the opposite way.

The following snippet is my UIPanGestureRecognizer delegate implementation:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
    CGPoint velocity = [panGestureRecognizer velocityInView:panGestureRecognizer.view];
    return fabs(velocity.y) > fabs(velocity.x);
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    if (otherGestureRecognizer == panGestureOfSubView) {
        return YES;
    }

    return NO;
}
1
votes

This code might be helpful. It's what I wrote to allow dragging for a specific view, but not for its subviews:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        if gestureRecognizer == longTouchGesture && otherGestureRecognizer == panTouchGesture && gestureRecognizer.view?.hitTest(gestureRecognizer.locationInView(gestureRecognizer.view), withEvent: nil) == self {
            print("returning true")
            return true
        }
        print("returning false")
        return false
    }