手势冲突~

丌官坚秉
2023-12-01

转载([https://blog.csdn.net/u012891546/article/details/52411541](https://link.jianshu.com?t=https%3A%2F%2Fblog.csdn.net%2Fu012891546%2Farticle%2Fdetails%2F52411541))

iOS系统中,滑动返回手势,其实是一个UIPanGestureRecognizer,系统默认的操作是只有滑动屏幕的左边的某个位置,UIPanGestureRecognizer才会起作用。UIScrollView的滑动手势也是UIPanGestureRecognizer。UIGestureRecognizer和UIView是多对一的关系([具体点这里](https://link.jianshu.com?t=https%3A%2F%2Fdeveloper.apple.com%2Flibrary%2Fios%2Fdocumentation%2FEventHandling%2FConceptual%2FEventHandlingiPhoneOS%2FGestureRecognizer_basics%2FGestureRecognizer_basics.html%23%2F%2Fapple_ref%2Fdoc%2Fuid%2FTP40009541-CH2-SW2)),UIGestureRecognizer一定要和view进行绑定才能发挥作用。因此不难想象,UIGestureRecognizer对于屏幕上的手势事件,其接收顺序和UIView的层次结构是一致的

UINavigationController.view —> UIViewController.view —> UIScrollView —> Screen and User's finger

即UIScrollView的panGestureRecognizer先接收到了手势事件,直接就地处理而没有往下传递。

实际上这就是两个panGestureRecognizer共存的问题。

由于scrollView的滑动手势拦截了事件,那我重写scrollView中panGestureRecognizer的代理方法,让它不拦截就好了嘛。于是继承UIScrollView,重写下面的方法。

//一句话总结就是此方法返回YES时,手势事件会一直往下传递,不论当前层次是否对该事件进行响应。

*   (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

    if ([selfpanBack:gestureRecognizer]) {

    ```
      returnYES;

    ```

    }

    returnNO;

}

//location_X可自己定义,其代表的是滑动返回距左边的有效长度

*   (BOOL)panBack:(UIGestureRecognizer *)gestureRecognizer {

    int location_X =40;

    if (gestureRecognizer ==self.panGestureRecognizer) {

    ```
      UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;

      CGPoint point = [pantranslationInView:self];

      UIGestureRecognizerState state = gestureRecognizer.state;

      if (UIGestureRecognizerStateBegan == state ||UIGestureRecognizerStatePossible == state) {

          CGPoint location = [gestureRecognizerlocationInView:self];

          if (point.x >0 && location.x < location_X &&self.contentOffset.x <=0) {

              returnYES;

          }

      }

    ```

    }

    returnNO;

}

需要侧边滑动时 panBack 返回YES,这时候,我让scrollView的手势和页面的滑动返回手势共存,scrollView不拦截手势,那不就可以滑动返回了吗。好了,测试一下,可以滑动返回,但是滑动返回时,scrollView也跟着在滑动呢,我们应该让scrollView切换的时候相应panGesture,滑动返回的时候不响应,那重写scrollView中的另外一个panGestureRecognizer的代理方法。

*   (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

    if ([self panBack:gestureRecognizer]) {

    ```
      return NO;

    ```

    }

    return YES;

}

以上的代码都是在一个自定义的UIScrollView上的,重写上面的方法即可。然后让横向滚动的scrollView继承这个自定义UIScrollView就OK了。

另外要注意重写的自定义的UIScrollView要记得实现协议 UIGestureRecognizerDelegate

原理:
scrollView的pan手势会让系统的pan手势失效,所以我们只需要在系统手势失效且scrollView的位置在初始位置的时候让两个手势同时启用就可以了。
 

 类似资料: