问题一:和scrollView的横滑手势冲突
场景分析
scrollview上添加了多个页面,横滑实现切换页面,当滑动到第一个页面时,右滑手势不能打开左侧菜单。
解决思路
UIView和手势相关的方法中,除了有addGestureRecognizer
和removeGestureRecognizer
外,还有下面这个方法:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
官方文档中的描述
Asks the view if the gesture recognizer should be allowed to continue tracking touch events.
Subclasses may override this method and use it to prevent the recognition of particular gestures.
At the time this method is called, the gesture recognizer is in the UIGestureRecognizerStatePossible state and thinks it has the events needed to move to the UIGestureRecognizerStateBegan.
The default implementation of this method returns YES.
大概意思是:询问视图是否允许手势识别器继续跟踪触摸事件。子类可以重写该方法用以阻止特定手势的识别。这个方法调用时,手势识别器的状态是 UIGestureRecognizerStatePossible ,并且考虑是否有需要改变到 UIGestureRecognizerStateBegan 状态的事件。
所以,在手势识别器由 possible 的默认状态切换成 began 之前,会调用这个方法,判断是否可以切换到 began 状态,切换到 began 状态后,手势识别器就会向target 发送动作消息。所以重写该方法,针对特定的手势,返回 NO,从而阻止手势识别器的识别。
解决方法
直接上代码
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
// 处于第一页且向左滑时
if (self.contentOffset.x == 0 && [pan translationInView:self].x > 0) {
return NO;
}
}
return [super gestureRecognizerShouldBegin:gestureRecognizer];
}
在自定义的 UIScrollView 的子类中,重写以上方法。判断拖拽手势的是否向右和 scrollView 是否已经滑动到左边缘,如果满足这两个条件,则阻止 scrollView 对拖拽手势的识别,交给父视图处理。
与tableViewCell的左滑手势冲突
场景分析
项目中的 leftViewController 是一个UITableViewController 对象,cell 支持左滑删除,但是mmDrawer中左滑 leftView 会关闭抽屉效果。
因为左滑 leftView 关闭抽屉效果,并不是必须的功能,仅需要支持点击 centerView 或者左滑 centerView 关闭抽屉即可。
所以发现MMDrawerController 有MMCloseDrawerGestureMode
属性。可以改变该属性,从而改变关闭抽屉支持的手势。
解决方法。
上代码:
[self.drawerController setCloseDrawerGestureModeMask:MMCloseDrawerGestureModePanningCenterView|MMCloseDrawerGestureModeTapCenterView];
该属性是枚举类型,
typedef NS_OPTIONS(NSInteger, MMCloseDrawerGestureMode) {
MMCloseDrawerGestureModeNone = 0,
MMCloseDrawerGestureModePanningNavigationBar = 1 << 1,
MMCloseDrawerGestureModePanningCenterView = 1 << 2,
MMCloseDrawerGestureModeBezelPanningCenterView = 1 << 3,
MMCloseDrawerGestureModeTapNavigationBar = 1 << 4,
MMCloseDrawerGestureModeTapCenterView = 1 << 5,
MMCloseDrawerGestureModePanningDrawerView = 1 << 6,
MMCloseDrawerGestureModeCustom = 1 << 7,
MMCloseDrawerGestureModeAll = MMCloseDrawerGestureModePanningNavigationBar |
MMCloseDrawerGestureModePanningCenterView |
MMCloseDrawerGestureModeBezelPanningCenterView |
MMCloseDrawerGestureModeTapNavigationBar |
MMCloseDrawerGestureModeTapCenterView |
MMCloseDrawerGestureModePanningDrawerView |
MMCloseDrawerGestureModeCustom,
};
可自由选择或组合支持的手势,只要不支持 MMCloseDrawerGestureModePanningDrawerView ,就不会和 cell 左滑删除产生冲突。
总结
使用侧滑菜单,容易产生各种各样的手势冲突,所谓“做的越多,错的越多”,支持的手势类型越多,越容易产生冲突,满足常见需求的前提下,尽量减少不需要支持的手势。