如何解决tableView(UIScrollView)与其subview的手势冲突问题

最近做的一个项目,基本情况可以这样描述:一个tableView,每个cell占据一个页面,paging enabled属性设置为YES,那么上下滑动会翻页,每个cell都有一个立方体:

手势冲突1.gif

然后我希望每个cell都可以在手指左右滑的时候,立方体能够旋转!你会想到加一个手势不就行了么,是的,我也是这么做的:

        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
        pan.delegate = self;
        [self.contentView addGestureRecognizer:pan];

- (void)handlePan:(UIPanGestureRecognizer *)pan
{
    CGPoint point = [pan translationInView:self];
    switch (pan.state)
    {
        case UIGestureRecognizerStateBegan:
            self.prePoint = point;
            break;
            
        case UIGestureRecognizerStateChanged:
            [self changeCubeWithPoint:point prePoint:self.prePoint screenSize:self.screenSize];
            self.prePoint = point;
            break;
            
        default:
            break;
    }
}

但是你很快会发现,你的cell中的立方体确实在转动,但是不能上下翻页了。很显然是UIPanGestureRecognizer和scrollView的滑动手势冲突了,解决办法是设置UIPanGestureRecognizer的代理UIGestureRecognizerDelegate,并实现代理方法:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

-(BOOL)gestureRecognizer(UIGestureRecognizer*)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer方法的含义是该手势能否与其它手势一起被识别,如果按照上面这样写,你会发现确实既可以滑动又可以转立方体了,但是滑动立方体的时候,你会很容易就误翻页了,tableView太不听话了。真正希望的效果是在横向滑动的时候,立方体转动但是tableView别乱动,快速上下滑的时候tableView再翻页!把上面的方法改成下面的:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])
    {
        switch (gestureRecognizer.state)
        {
            case UIGestureRecognizerStateBegan:
            {
                UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
                CGPoint velocity = [pan velocityInView:self];
                CGFloat Vx = fabs(velocity.x);
                CGFloat Vy = fabs(velocity.y);
                
                return !(Vx > Vy - 50.0 || Vy < 400.0 || Vx > 500.0);
            }
                break;
                
            case UIGestureRecognizerStateChanged:
                return NO;
                break;
                
            default:
                break;
        }
    }
    
    return YES;
}

意思就是手势开始的时候,如果发现横向滑动速度Vx比较大的时候,不要去滑动tableView了,如果UIPanGestureRecognizer手势开始了(UIGestureRecognizerStateChanged),也不要去滑动了,只有当开始的时候上下滑速度Vy比较大的时候,才去滑动tableView,达到了我们要的效果:


手势冲突2.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 事情起因是新项目,产品要做杂志翻页风格,也不不显示导航、标签栏、返回键,返回由下滑手势出发,上滑会从底部显示足迹,...
    vincent涵阅读 6,316评论 6 9
  • 在第十八章中,您通过实现 UIResponder 的方法来处理原始触摸。 有时你想检测一个特定的触摸模式——手势,...
    titvax阅读 1,302评论 6 3
  • 在iOS开发中经常会涉及到触摸事件。本想自己总结一下,但是遇到了这篇文章,感觉总结的已经很到位,特此转载。作者:L...
    WQ_UESTC阅读 6,114评论 4 26
  • 好奇触摸事件是如何从屏幕转移到APP内的?困惑于Cell怎么突然不能点击了?纠结于如何实现这个奇葩响应需求?亦或是...
    Lotheve阅读 57,983评论 51 603
  • 这对兔子在心中长草许久了,终于如愿以偿地做好了它们,没有想到的那么难。 许多事情就是如此,只有尝试了才知道到底难不...
    叶样悠阅读 255评论 1 4