解决右滑返回手势和UIScrollView中的手势冲突

首先说一下我们项目是怎么简单解决的

@interface BaseNav : UINavigationController
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationBar.hidden = YES;
    
    
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (self.viewControllers.count >= 1)
    {
        viewController.hidesBottomBarWhenPushed = YES;
    }
    [super pushViewController:viewController animated:animated];
    self.interactivePopGestureRecognizer.delegate = self;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    BOOL ok = YES; // 默认为支持右滑反回
    if ([self.topViewController isKindOfClass:[XTYBaseWebViewController class] ]|| [self.topViewController isKindOfClass:[GenericWebViewController class] ]||[self.topViewController isKindOfClass:[TempActViewController class] ]) {
        ok = NO;
    }
    return ok;
}

当让这可能不是最好的解决方案 于是又是在网上各种查
出现的原因

iOS系统中,滑动返回手势,其实是一个UIPanGestureRecognizer,系统默认的操作是只有滑动屏幕的左边的某个位置,UIPanGestureRecognizer才会起作用。UIScrollView的滑动手势也是UIPanGestureRecognizer。UIGestureRecognizer和UIView是多对一的关系(具体点这里),UIGestureRecognizer一定要和view进行绑定才能发挥作用。因此不难想象,UIGestureRecognizer对于屏幕上的手势事件,其接收顺序和UIView的层次结构是一致的

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

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

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

解决方案一

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    
    if ([self panBack:gestureRecognizer]) {
        return NO;
    }
    return YES;
    
}
- (BOOL)panBack:(UIGestureRecognizer *)gestureRecognizer {
    
    if (gestureRecognizer == self.panGestureRecognizer) {
        UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
        CGPoint point = [pan translationInView:self];
        UIGestureRecognizerState state = gestureRecognizer.state;
        if (UIGestureRecognizerStateBegan == state || UIGestureRecognizerStatePossible == state) {
            CGPoint location = [gestureRecognizer locationInView:self];
            if (point.x > 0 && location.x < 20 && self.contentOffset.x <= 0) {
                return YES;
            }
        }
    }
    return NO;
    
}

解决方案二

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    // 首先判断otherGestureRecognizer是不是系统pop手势
    if ([otherGestureRecognizer.view isKindOfClass:NSClassFromString(@"UILayoutContainerView")]) {
        // 再判断系统手势的state是began还是fail,同时判断scrollView的位置是不是正好在最左边
        if (otherGestureRecognizer.state == UIGestureRecognizerStateBegan && self.contentOffset.x == 0) {
            return YES;
        }
    }
    
    return NO;
}

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

下面一个 git 连接 运动 runtime 来做的侧滑返回

https://github.com/W-King/PPX_LateralSpreads

你可能感兴趣的:(解决右滑返回手势和UIScrollView中的手势冲突)