Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolve conflict between two pan gesture recognizers

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;
    }
like image 858
Rob Zombie Avatar asked Sep 01 '25 06:09

Rob Zombie


2 Answers

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;
}
like image 95
夜一林风 Avatar answered Sep 02 '25 19:09

夜一林风


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
    }
like image 43
Eden Avatar answered Sep 02 '25 20:09

Eden