iOS之事件穿透
前言
小伙伴们在开发中是否遇到过这样的需求呢,一个控件的某个部分被另外一个控件遮挡住,当点击这个重叠部分时,需要响应被遮盖控件的点击事件,就如下图所示
当我们点击区域3时,响应蓝色按钮的点击事件,点击区域1和2时,响应红色按钮的点击事件,对于区域1和3没什么好说的,那如何让红色按钮响应区域2的点击呢?这就是笔者今天要讲的内容。
事件传递
大家应该都知道,事件从应用程序开始,按照从上到下的顺序(UIApplication -> UIWindow -> rootViewController -> ...)一级一级传递,并且系统在寻找最适合处理事件的控件时,是从后往前遍历子控件的(网上资料太多,不做详细阐述,请自行百度)
上图中蓝色按钮在红色按钮之后添加,当系统寻找最适合的控件时,蓝色按钮在红色按钮之前被找到,系统发现蓝色按钮很适合处理事件,所以方法便返回了,红色按钮就没有了处理事件的机会。
系统如何寻找最适合控件
- 判断自己能否接受触摸事件,如果不能,返回nil
- 判断触摸点是否在自己身上,如果不能,返回nil
- 从后往前遍历子控件,重复上面的步骤,如果没有适合的子控件,返回自己
我们来看看系统内部是如何实现的,笔者这里自定义了一个UIWindow,让它成为主窗口,并重写它的hitTest方法,运行之后,其事件处理功能,与系统的类似,所以系统内部大概就是这样实现的
当一个控件的透明度小于某个值时,就不再响应事件,上图中0.01仅仅是为了测试,并非准确的值,要注意的就是,对于继承自UIControl的控件,还需要判断enable的值
事件穿透
既然系统寻找最合适控件的方法满足不了我们,那我们就重写系统的方法
思路
- 点击蓝色按钮的区域2,红色按钮响应事件,那肯定要重写蓝色按钮的hitTest方法
- 在hitTest方法中,将触摸点的坐标系从蓝色按钮转换到红色按钮上,即以红色按钮左上角为原点
- 坐标系转换后,判断触摸点是否在红色按钮上,如果是,直接返回红色按钮(严谨一点的做法是调用红色按钮的hitTest方法),如果不是,那就调用系统的方法,让系统去处理
有了思路,那万事具备只欠东风了,接下来上东风
新建一个类,继承自UIButton,笔者这里直接命名为BlueButton,修改sb\xib中蓝色按钮的类型为BlueButton
将红色按钮连线到BlueButton.m文件中,不用试了,直接连是连不了的,我们可以先在BlueButton.m中定义一个属性,前面加上IBOutlet,然后单击图中的空心圆,拖到红色按钮上就OK了
最后,在BlueButton.m中重写蓝色按钮的hitTest方法,代码如下
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGPoint redBtnPoint = [self convertPoint:point toView:_redButton];
if ([_redButton pointInside:redBtnPoint withEvent:event]) {
return _redButton;
}
//如果希望严谨一点,可以将上面if语句及里面代码替换成如下代码
//UIView *view = [_redButton hitTest: redBtnPoint withEvent: event];
//if (view) return view;
return [super hitTest:point withEvent:event];
}
来看运行结果,点击区域2时,红色按钮高亮并响应事件

iOS之事件穿透的更多相关文章
- 支持事件穿透?使用pointer-events样式
使用绝对定位元素,让元素A完全盖住元素B时,如何通过元素A来响应元素B的事件呢? 上图可以用下面的SVG代码来实现: <svg width="200" height=&quo ...
- 手机端 zepto tap事件穿透
什么是事件穿透? 点击上面的一层时会触发下面一层的事件 ”google”说原因是“tap事件实际上是在冒泡到body上时才触发”,也就是Zepto的tap事件是绑定在document上的,所以会导致 ...
- IOS触摸事件和手势识别
IOS触摸事件和手势识别 目录 概述 触摸事件 手势识别 概述 为了实现一些新的需求,我们常常需要给IOS添加触摸事件和手势识别 触摸事件 触摸事件的四种方法 -(void)touchesBegan: ...
- IOS——触摸事件 视图检测和事件传递
iPhone上有非常流畅的用户触摸交互体验,能检测各种手势:点击,滑动,放大缩小,旋转.大多数情况都是用UI*GestureRecognizer这样的手势对象来关联手势事件和手势处理函数.也有时候,会 ...
- IOS 触摸事件分发机制详解
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:MelonTeam 前言 很多时候大家都不关心IOS触摸事件的分发机制的实现原理,当遇到以下几种情形的时候你很可能抓破头皮都找不到解决方案 ...
- 如何让触摸事件穿透一个View
如何让触摸事件穿透一个View 偶然间发现,如何屏蔽或者让触摸事件穿透一个view是一个很简单的事情. 现象: 源码: // // ViewController.m // UserInteractio ...
- Jquery 在ios上事件委托失效
点击通过js遍历出来的列表,跳转页面.点击事件委托在document上, 像这样: $(document).on("click",".nav",function ...
- [原创]实现多层DIV叠加的js事件穿透
Flash里面有个很好的特性是,一个容器里,不存在实际对象的部分,不会阻拦鼠标事件穿透到下一层. 前端就不一样了,两个div层叠以后,上层div会接收到所有事件(即使这个div里面内容是空的,没有任何 ...
- iOS开发事件分发机制—响应链—手势影响
1.提纲 什么是iOS的事件分发机制 ? 一个事件UIEvent又是如何响应的? 手势对于响应链有何影响? 2.事件分发机制 2.1.来源 以直接触摸事件为例: 当用户一个手指触摸屏幕是会生成一个UI ...
随机推荐
- 【转】跟着开涛学SpringMVC
跟着开涛学SpringMVC 第一章源代码下载 博客分类: 跟开涛学SpringMVC 跟开涛学SpringMVC 源代码请到附件中下载. 其他下载: 跟着开涛学SpringMVC 第一章源代码下载 ...
- 关于 mkimage
在嵌入式系统中,Linux内核和根文件系统一般都与bootloader一起烧写在flash芯片中,系统启动后,bootloader将Linux内核压缩到RAM中,并把压缩的根文件系统复制到RAM中,然 ...
- 如何升级cordova插件
cordova-plugin-code-push插件在cordova6.1.1 ios环境中出现异常. 所以尝试升级cordova-plugin-code-push来解决这个问题. 升级没有被依赖的插 ...
- redis-3.0.0集群的安装及使用
redis集群需要至少6个节点(偶数节点),3个主节点,3个从节点.注意:集群模式最好不要keys *查询数据. 1 下载redis,官网下载3.0.0版本,之前2.几的版本不支持集群模式.下载地址: ...
- Velocity是如何工作的
当在一个应用程序或者servlet中使用Velocity的时候,你要做如下几个工作: 初始化Velocity.Velocity提供2种使用形式,不管是单一实例模式还是单独运行实例模式,初始化过程都只做 ...
- python 遇到 syntaxerror: non-ascii character '/xd6' in file 我 教你解决 (python问题)(转)
遇到标题上的问题,按照我的解决广方案来吧 ===================================== (一) 用记事本创建一个文件ChineseTest.py,默认ANSI: s = ...
- mac中viso的兼容工具
http://www.orsoon.com/Mac/77738.html破解教程 http://www.pc6.com/mac/111747.html下载地址 很强大,很爽.
- 问题:如何在固定大小的DIV层插入N多个图片
这是贴友问的一个问题,具体需求是: 如何在固定大小的DIV层插入N多个图片,使其一行排列,超出层宽时出现滑动条? 原以为利用overflow属性可以实现,但是测试失败.后来利用div层叠实现了效果. ...
- 进程隐藏与进程保护(SSDT Hook 实现)(二)
文章目录: 1. 引子 – Demo 实现效果: 2. 进程隐藏与进程保护概念: 3. SSDT Hook 框架搭建: 4. Ring0 实现进程隐藏: 5. Ri ...
- uva 11997 K Smallest Sums 优先队列处理多路归并问题
题意:K个数组每组K个值,每次从一组中选一个,共K^k种,问前K个小的. 思路:优先队列处理多路归并,每个状态含有K个元素.详见刘汝佳算法指南. #include<iostream> #i ...