iOS 全屏侧滑/UIScrollView/UISlider间滑动冲突
效果预览

一、前期准备
有一个支持全屏侧滑返回的视图控制器ViewController,ViewController.view上有一个UIScrollView,UIScrollView上有UISlider。俺直接在之前的示例Demo上演示,地址:iOS 自定义转场动画
二、问题展示
- 现象 1、UIScrollView当前在第一页即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;
}
四、应用示例

五、项目结构

好了,俺要去鹊桥跟俺家织女相会咯✌️
iOS 全屏侧滑/UIScrollView/UISlider间滑动冲突的更多相关文章
- 原生JS实现全屏切换以及导航栏滑动隐藏及显示——重构前
思路分析: 向后滚动鼠标滚轮,页面向下全屏切换:向前滚动滚轮,页面向上全屏切换.切换过程为动画效果. 第一屏时,导航栏固定在页面顶部,切换到第二屏时,导航条向左滑动隐藏.切换回第一屏时,导航栏向右滑动 ...
- iOS - 全屏滑动
取经地址 1.使用关联 关联是指把两个对象相互关联起来,使得其中的一个对象作为另一个对象的一部分. 使用关联,是基于关键字的,因此,我们可以为任意对象增加任意多的关联,但是关键字是唯一的.关联可以保证 ...
- iOS 全屏布局
edgesForExtendedLayout属性用于替代wantsFullScreenLayout,控制页面显示的范围,默认值是UIRectEdgeAll automaticallyAdjustsSc ...
- iOS 全屏播放网页视频退出后状态栏被隐藏
使用wkWebView播放网页上的视频,播放完成后,退出视频返回到网页发现app的状态整个被隐藏了,解决方法,监听状态栏隐藏通知,在适当的时候让状态栏显示出来 [[NSNotificationCent ...
- UIScrollView的左右滑动和侧滑手势冲突的解决办法
转载自:https://blog.csdn.net/kst_123/article/details/77762811 当ViewController中添加了一个全屏的UIScrollView的时候,U ...
- iOS任何界面全屏炫酷倒计时,一句代码就够了
概述 iOS全屏炫酷倒计时,任何界面只需要调用一句代码就能实现,支持定制倒计时数字.倒计时结束时显示的文本.支持倒计时播放图片.开始倒计时和结束倒计时的block和delegate回调.支持定制文本颜 ...
- uni-app仿抖音APP短视频+直播+聊天实例|uniapp全屏滑动小视频+直播
基于uniapp+uView-ui跨端H5+小程序+APP短视频|直播项目uni-ttLive. uni-ttLive一款全新基于uni-app技术开发的仿制抖音/快手短视频直播项目.支持全屏丝滑般上 ...
- swift - 全屏pop手势
UINavigationController系统自带有侧滑手势,但是这个手势第一点只能边缘侧滑才可以有效,第二点当手动隐藏系统的导航时,这个手势就不能生效了 为了能到达到全屏pop的效果这里有2中解决 ...
- 解决微信浏览器内video全屏问题
前端离职,让我写个视频播放页面,木办法只有我来搞了. 默认用h5的 video标签 测试时候发现微信浏览器内访问video自动全屏播放. 搜了下 webkit-playsinline="tr ...
随机推荐
- Educational Codeforces Round 11 B. Seating On Bus 水题
B. Seating On Bus 题目连接: http://www.codeforces.com/contest/660/problem/B Description Consider 2n rows ...
- Linux知识(6)----VIM
vi的第一版是由Bill Joy在1978年写成的,当时他是UC Berkeley的学生.后来他共同创建了神奇的Sun公司.vi来源于visual一词,目标是在终端上可视化地模拟文本的编辑,是的更人性 ...
- timeago.js-时间显示插件
注意事项: 1. 时间格式 = “2018-03-02 17:13:00”时,动态获取的时间无法通过 拼接字符串的方法 添加到 dom元素的 datetime属性上,结果为 <div class ...
- HDU 4671 Backup Plan (2013多校7 1006题 构造)
Backup Plan Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total ...
- 实战DELPHI:远程线程插入(DLL注入)
http://www.jx19.com/xxzl/Delphi/2010/04/17/ShiZhanDELPHI_YuanChengXianChengChaRu_DLLZhuRu/ 远程注入DLL方法 ...
- SQL SERVER SQLOS的任务调度--微软亚太区数据库技术支持组 官方博客
https://blogs.msdn.microsoft.com/apgcdsd/2011/11/23/sql-server-sqlos/
- 【资料】wod强壮护符
泛用耗材 损坏的 卡罗先活力护符 小型的 强壮护符 改良的 鲁比斯护符 否定护符 活跃护符 自然防御护符 防御疾病护符 特定职业使用耗材护符 野蛮人 诗人 祭司 泛用 仪式用巴博许教的 ...
- linux、mac的bash和zsh如何切换
1.hostname 192-23-2-2 修改主机名字 2.chsh -s /bin/bash和chsh -s /bin/zsh可以永久切换,也就是一登录进来的就是相应的界面 bash/zsh命令是 ...
- Spring Bean 注入 1 - 构造方法注入,属性注入,自动装配
1.代码结构图 xxx 2.bean代码 package com.xxx.bean; /** * Created with IntelliJ IDEA. * User: zhenwei.liu * D ...
- iOS:沙盒、偏好设置、归档、解归档
一.沙盒和应用程序包 •iOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被称为沙盒 •iOS常用目录: –Bundle –Documents –Library/Ca ...