欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-10-08 22:51:54
ios中,滑动返回手势,其实是一个uipangesturerecognizer,系统默认的操作是只有滑动屏幕的左边的某个位置,uipangesturerecognizer才会起作用。uiscroll...

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

uinavigationcontroller.view —> uiviewcontroller.view —> uiscrollview —> screen and user's finger

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

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

由于scrollview的滑动手势拦截了事件,那我重写scrollview中pangesturerecognizer的代理方法,让它不拦截就好了嘛。于是继承uiscrollview,重写下面的方法。

//一句话总结就是此方法返回yes时,手势事件会一直往下传递,不论当前层次是否对该事件进行响应。

- (bool)gesturerecognizer:(uigesturerecognizer *)gesturerecognizer shouldrecognizesimultaneouslywithgesturerecognizer:(uigesturerecognizer *)othergesturerecognizer {
if ([self panback:gesturerecognizer]) {
return yes;
}
return no;
}

//location_x可自己定义,其代表的是滑动返回距左边的有效长度

- (bool)panback:(uigesturerecognizer *)gesturerecognizer {
int location_x = 100;
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 < location_x && self.contentoffset.x <= 0) {
return yes;
}
}
}
return no;}

需要侧边滑动时 panback 返回yes,这时候,我让scrollview的手势和页面的滑动返回手势共存,scrollview不拦截手势,那不就可以滑动返回了吗。好了,测试一下,可以滑动返回,但是滑动返回时,scrollview也跟着在滑动呢,我们应该让scrollview切换的时候相应pangesture,滑动返回的时候不响应,那重写scrollview中的另外一个pangesturerecognizer的代理方法。

- (bool)gesturerecognizershouldbegin:(uigesturerecognizer *)gesturerecognizer {

if ([self panback:gesturerecognizer]) {

return no;

}

return yes;

}

以上的代码都是在一个自定义的uiscrollview上的,重写上面的方法即可。然后让横向滚动的scrollview继承这个自定义uiscrollview就ok了。

另外要注意重写的自定义的uiscrollview要记得实现协议uigesturerecognizerdelegate

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