代码地址如下:
http://www.demodashi.com/demo/13848.html

效果预览

一、前期准备

有一个支持全屏侧滑返回的视图控制器ViewController,ViewController.view上有一个UIScrollView,UIScrollView上有UISlider。俺直接在之前的示例Demo上演示,地址:iOS 自定义转场动画

二、问题展示

  • 现象 1UIScrollView当前在第一页即contentOffset.x=0时,左滑不能触发全屏侧滑pop返回的手势

  • 现象2问题1解决后,你会发现拖拽UIScrollView第一页上的UISlider时,向右拖拽时却触发了全屏侧滑pop返回的手势,而UISlider本身的拖拽事件却没有响应;向左拖拽UISlider时,响应的是UIScrollView的拖动事件,而UISlider本身的拖拽事件也没有响应

  • 现象3当你长按UISlider超过150ms后直接拖拽,就不存在现象2中UISlider与UIScrollView、全屏侧滑返回的冲突问题了

三、分析解决问题

这些问题很显然,肯定跟iOS事件的传递和响应链机制有关系,不了解的可以看看这篇文章 史上最详细的iOS之事件的传递和响应机制-原理篇

  • 分析解决问题 1

    如果你了解事件的传递和响应链机制的话,应该能想到,是由于UIScrollView的内部手势方法阻断了全屏侧滑返回手势的的响应,那我们就找到这个方法,代码如下

创建一个UIScrollView的类别UIScrollView+GestureConflict,重写如下方法:

//处理UIScrollView上的手势和侧滑返回手势的冲突
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ // 首先判断otherGestureRecognizer是不是系统pop手势
if ([otherGestureRecognizer.view isKindOfClass:NSClassFromString(@"UILayoutContainerView")]) {
// 再判断系统手势的state是began还是fail,同时判断scrollView的位置是不是正好在最左边
if (otherGestureRecognizer.state == UIGestureRecognizerStateBegan && self.contentOffset.x == 0) {
return YES;
}
}
return NO;
}
  • 分析解决问题 2和3

方案一:这个跟UIScrollView的一个属性delaysContentTouches有关。

scrollView.delaysContentTouches = NO;

delaysContentTouches 默认值为YES 表示延迟scrollView上子视图的响应,所以当直接拖动UISlider时,如果此时touch时间在150ms以内,UIScrollView会认为是拖动自己,从而拦截了event,导致UISlider接收不到滑动的event。但是只要长按住UISlider一会儿再拖动,此时touch时间超过150ms,因此滑动的event会发送到UISlider上,然后UISlider再作出响应;设置为NO后,拖动UISlider时就可以直接做出响应,解决了UISlider与UIScrollView之间的冲突,同时也解决了向右拖拽时却触发了全屏侧滑pop返回的问题。

方案二: 重写类别UIScrollView+GestureConflict中的如下方法来解决UISlider与UIScrollView之间的冲突,然后还需要执行下面 问题补充 中的操作来处理UISlider的滑动与全屏侧滑pop返回事件的冲突。

//拦截事件的处理 事件传递给谁,就会调用谁的hitTest:withEvent:方法。
//处理UISlider的滑动与UIScrollView的滑动事件冲突
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
/*
直接拖动UISlider,此时touch时间在150ms以内,UIScrollView会认为是拖动自己,从而拦截了event,导致UISlider接受不到滑动的event。但是只要按住UISlider一会再拖动,此时此时touch时间超过150ms,因此滑动的event会发送到UISlider上。
*/
UIView *view = [super hitTest:point withEvent:event]; if([view isKindOfClass:[UISlider class]]) {
//如果接收事件view是UISlider,则scrollview禁止响应滑动
self.scrollEnabled = NO;
} else { //如果不是,则恢复滑动
self.scrollEnabled = YES;
}
return view;
}
  • 问题补充

    示例Demo中的UISlider是在UIScrollView上的,如果UISlider不是在UIScrollView上,而是直接就在ViewController.view上,那也就会出现拖拽UISlider时却响应了全屏侧滑pop返回手势的问题。

在支持全屏侧滑返回的UINavigationController的子类WSLNavigatioController中,遵守协议,实现如下方法:

#pragma mark -- UIGestureRecognizerDelegate
//触发之后是否响应手势事件
//处理侧滑返回与UISlider的拖动手势冲突
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
//如果手势是触摸的UISlider滑块触发的,侧滑返回手势就不响应
if ([touch.view isKindOfClass:[UISlider class]]) {
return NO;
}
return YES;
}

四、应用示例

五、项目结构

好了,俺要去鹊桥跟俺家织女相会咯✌️

最新文章

  1. Autodesk View and Data API二次开发学习指南
  2. div层调整zindex属性无效原因分析及解决方法
  3. Also unsere eigene Christian Louboutin Webshop bietet die überragende Christian Louboutin Schuhe uk schiebt zusammen mit kostengünstigen Wert
  4. 开启梦幻般的webrtc之旅
  5. CSS行高line-height的理解
  6. MySQL助理配置
  7. Java transient关键字序列化时使用小记
  8. 【转】MYSQL入门学习之十二:存储过程的基本操作
  9. HDU 1681 Frobenius
  10. sql server 2005中使用with实现递归
  11. 理解数据点,自变量和因变量(参数和值)ChartControl
  12. 管理 sendmail 的邮件队列
  13. iOS开发- 查询项目代码行数
  14. js框架Modernizr是什么东西? 他是前端开发HTML5和CSS3的强有力前端js检测类库
  15. robotium问答
  16. 关于laravel 得手动分页问题
  17. Azure Powershell获取指定订阅下的虚拟机信息(ASM)
  18. 线段树模板1 [Luogu P3372]
  19. import和require的区别
  20. 【LOJ】#2081. 「JSOI2016」反质数序列

热门文章

  1. 一个iframe注入漏洞,也是微软的 Application["error"] 漏洞
  2. hibernate 开发步骤
  3. Java Http连接中(HttpURLConnection)中使用代理(Proxy)及其验证(Authentication)
  4. Java常量定义需要注意的两点
  5. 开发Google Material Design风格的WPF程序
  6. 用css让一个容器水平垂直居中
  7. 使用WCF测试客户端 z
  8. ipad2 wifi ios7.x 1.0.1还是无法越狱
  9. uva 816 abbott's revenge ——yhx
  10. webshell三剑客[aspxspy、phpspy、jspspy]