问题
在项目遇到了一个横向的 UIScrollView 嵌套两个 tableview,并且 right tableview 需要支持左滑删除 cell 的需求。
常规方案
找了一圈解决方案,大都是继承一个 UIScrollveiw,重写子类的
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (gestureRecognizer.state != UIGestureRecognizerStatePossible) {
return YES;
} else {
return NO;
}
}
该方法 return YES可以让手势同时被 scrollview 和 tableview 识别。
不过因为项目中已经用到 了UIPageViewController,无法去继承一 个UIscrollView。 沿着这个思路走下去,定义一个 UIScrollView 子类,设置 pageViewController.scrollview.panGestureRecognizer.delegate = 子类。 重写子类的
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
利用消息转发机制,将除此之外的子类其他方法转给原scrollview执行。 不过这个方法被 APPLE 否决了,APPLE 不允许我们修改 scrollview.panGestureRecognizer.delegate。
最终解决方案
最终解决方案是给 tableview 添加一个 gesture recognizer,
- 首先拿到 UIPageViewController 的 scrollview
UIScrollView *scrollView = nil;
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
scrollView = (UIScrollView *)view;
break;
}
}
- 给 tableview 添加一个 panGestureRecognizer,设置手势响应优先级,当 tableview 响应手势时,scrollview 不响应手势
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:nil];
panGesture.delaysTouchesBegan = YES;
panGesture.cancelsTouchesInView = NO;
panGesture.delegate = self;
[self.tableView addGestureRecognizer:panGesture];
self.scrollView.canCancelContentTouches = YES;
[self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:panGesture];
- 实现代理方法
当 gesture recognizer 从 possible 状态转换为其他状态时,会调用此方法。
该方法 return NO 导致 gesture recognizer 进入 failed 状态手势不会再被识别。
当从右向左划删除cell的时候,translation.x是负值,所以当translation.x < 0时,给该方法 return YES 去继续识别 cell 左滑删除手势。若是从左往右滑,translation.x 为正值,该方法 return NO,tableveiw 的 gesture recognizer 进入 failed 状态,scrollview 会响应手势,滑动到 left tableview。
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (![gestureRecognizer isMemberOfClass:[UIPanGestureRecognizer class]]) {
return NO;
}
UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer;
CGPoint translation = [panGesture translationInView:self.tableView];
return translation.x < 0;
}
return YES 允许 tableview 和 scrollview 同时识别手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return otherGestureRecognizer.view == self.tableView;
}