解决两个平移手势识别器之间的冲突

Posted

技术标签:

【中文标题】解决两个平移手势识别器之间的冲突【英文标题】:Resolve conflict between two pan gesture recognizers 【发布时间】:2015-03-24 13:06:50 【问题描述】:

我有以下层次结构:

查看 子视图

每个视图都分配了UIPanGestureRecognizer。外部平移手势识别器只对垂直平移感兴趣,所以我为此实现了委托方法:

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

但是,Subview 的平移手势在识别中始终优先。有没有办法让外部平移手势识别器先识别,如果失败,子视图的平移手势可以接管?

我尝试同时识别并且它有效,但随后两个识别器都开始平移:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 

    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
        return YES;
    

【问题讨论】:

【参考方案1】:

ios 7 开始,UIGestureRecognizerDelegate 协议已经声明了两个代理方法来满足你的需要,你可以使用 |gestureRecognizer:shouldRequireFailureOfGestureRecognizer:| 或者 |gestureRecognizerShouldBegin:shouldBeRequiredToFailByGestureRecognizer:|但相反。

以下 sn-p 是我的 UIPanGestureRecognizer 委托实现:

- (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;

【讨论】:

谢谢伙计,我真的相信shouldBeRequiredToFailByGestureRecognizer 可以反过来工作,这就是为什么它显然不适合我。 我不知道为什么,但你的答案对我有用......显然,它在手势识别器和实际上应该失败但首先识别的手势识别器之间转移了一些优先级,另一个失败...... @Andy,两个delegate方法的第一个参数总是delegator,因为这种情况下只有两个手势,所以上面sn-p中的delegate方法只有在有gestureRecognizer参数时才返回YES附加到 superview 和附加到 subview 的 otherGestureRecognizer 参数。在这种情况下,根据sn-p,只有在superview的手势失败后才能识别subview的手势。【参考方案2】:

此代码可能会有所帮助。这是我写的允许拖动特定视图,但不允许其子视图:

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
    

【讨论】:

以上是关于解决两个平移手势识别器之间的冲突的主要内容,如果未能解决你的问题,请参考以下文章

使用平移手势识别器关闭视图控制器

使平移手势识别器仅在向下滑动时在桌面视图的顶部进行响应

带有平移手势冲突的滚动视图和侧边菜单

平移手势识别器的三层混淆

SWRevealViewController 平移手势识别器问题

如何禁用 UIScrollView 到平移手势识别器?