为何两种UIPanGestureRecognizer实现下UITableView滑动表现不同?
问题原因与解决方案
方式1问题原因
将UIPanGestureRecognizer直接添加到UITableView时,UITableView自身内置了用于滚动的UIPanGestureRecognizer,默认手势识别器遵循互斥规则——自定义手势会优先抢占触摸事件,导致系统自带的滚动手势无法触发,因此UITableView无法滑动,但自定义的panAction会正常执行。
方式2问题原因
将手势添加到父UIView时,触摸事件按视图层级从上到下传递,UITableView作为子视图会优先接收触摸事件,其内置的滚动手势会先识别并消耗事件,父视图的自定义UIPanGestureRecognizer无法获取到触摸事件,因此panAction不执行,但UITableView滚动正常。
通用解决方案
要让自定义UIPanGestureRecognizer和UITableView滚动同时生效,需利用手势代理方法强制允许两个手势同时识别:
- 给自定义手势设置代理:
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)]; panGesture.delegate = self; // 两种添加方式都适用 [self.tableView addGestureRecognizer:panGesture]; // 或者 [self.view addGestureRecognizer:panGesture];
- 实现代理方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { // 判断另一个手势是否为tableView的滚动手势 if ([otherGestureRecognizer.view isKindOfClass:[UITableView class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) { return YES; } return NO; }
如果是方式2(手势加在父view),需确保父view的userInteractionEnabled为YES,且无其他拦截事件的视图。若需在特定条件下触发自定义手势,可在代理方法中添加判断逻辑,比如根据滑动方向区分:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer; CGPoint translation = [pan translationInView:self.view]; // 仅水平滑动时触发自定义手势,垂直滑动留给tableView滚动 if (fabs(translation.x) > fabs(translation.y)) { return YES; } return NO; }
内容的提问来源于stack exchange,提问作者saipeng wang
相关产品推荐
相关产品推荐

