前言

小伙伴们在开发中是否遇到过这样的需求呢,一个控件的某个部分被另外一个控件遮挡住,当点击这个重叠部分时,需要响应被遮盖控件的点击事件,就如下图所示

 

当我们点击区域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之事件穿透的更多相关文章

  1. 支持事件穿透?使用pointer-events样式

    使用绝对定位元素,让元素A完全盖住元素B时,如何通过元素A来响应元素B的事件呢? 上图可以用下面的SVG代码来实现: <svg width="200" height=&quo ...

  2. 手机端 zepto tap事件穿透

    什么是事件穿透? 点击上面的一层时会触发下面一层的事件 ”google”说原因是“tap事件实际上是在冒泡到body上时才触发”,也就是Zepto的tap事件是绑定在document上的,所以会导致 ...

  3. IOS触摸事件和手势识别

    IOS触摸事件和手势识别 目录 概述 触摸事件 手势识别 概述 为了实现一些新的需求,我们常常需要给IOS添加触摸事件和手势识别 触摸事件 触摸事件的四种方法 -(void)touchesBegan: ...

  4. IOS——触摸事件 视图检测和事件传递

    iPhone上有非常流畅的用户触摸交互体验,能检测各种手势:点击,滑动,放大缩小,旋转.大多数情况都是用UI*GestureRecognizer这样的手势对象来关联手势事件和手势处理函数.也有时候,会 ...

  5. IOS 触摸事件分发机制详解

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:MelonTeam 前言 很多时候大家都不关心IOS触摸事件的分发机制的实现原理,当遇到以下几种情形的时候你很可能抓破头皮都找不到解决方案 ...

  6. 如何让触摸事件穿透一个View

    如何让触摸事件穿透一个View 偶然间发现,如何屏蔽或者让触摸事件穿透一个view是一个很简单的事情. 现象: 源码: // // ViewController.m // UserInteractio ...

  7. Jquery 在ios上事件委托失效

    点击通过js遍历出来的列表,跳转页面.点击事件委托在document上, 像这样: $(document).on("click",".nav",function ...

  8. [原创]实现多层DIV叠加的js事件穿透

    Flash里面有个很好的特性是,一个容器里,不存在实际对象的部分,不会阻拦鼠标事件穿透到下一层. 前端就不一样了,两个div层叠以后,上层div会接收到所有事件(即使这个div里面内容是空的,没有任何 ...

  9. iOS开发事件分发机制—响应链—手势影响

    1.提纲 什么是iOS的事件分发机制 ? 一个事件UIEvent又是如何响应的? 手势对于响应链有何影响? 2.事件分发机制 2.1.来源 以直接触摸事件为例: 当用户一个手指触摸屏幕是会生成一个UI ...

随机推荐

  1. C#中如何截取Windows消息来触发自定义事件

    原文 C#中如何截取Windows消息来触发自定义事件 在c#windows开发中,我们常常会遇到拦截windows消息,来触发某个特定任务的问题. 由于目前使用c#的开发人员非常多,而且大多数c#程 ...

  2. [转] ArcEngine中打开各种数据源(WorkSpace)的连接

    原文 ArcEngine中打开各种数据源(WorkSpace)的连接(SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源. ...

  3. 那些年一起踩过的坑 — Date类型序列化的问题

      坑在哪里?        序列化 和 反序列化 的时候对Date字段的格式设置不一致        例如:将Java bean序列化成Json string的时候 格式为 yyyy-MM-dd 解 ...

  4. 【Kafka入门】搭建Kafka本地环境

    本博文介绍如何一步步搭建起Kafka本地环境. 下载Kafka 0.9.0.0 并配置软链接 下载好后,放入电脑本地安装目录,mac下我放在/usr/local下,解压Kafka. -0.9.0.0. ...

  5. 集合框架-Map练习-记录字母出现的次数

    /* * 练习: * 字符串"abcb453   sddbs343bsjvAJBBDVBs21768723",获取该字符串中,每一个字母出现的次数. * 要求打印结果是:a(2)b ...

  6. PCb过孔大小设置 / 丝印层字符尺寸设置

    PCb过孔大小一般设置为:内孔(孔尺寸)0.30(12mil),外壳(直径)0.6(24mil) 常用过孔设置: 内径: 15mil(0.381mm)  30mil(0.762mm) 外径: 20mi ...

  7. [iOS基础控件 - 4.5] 猜图游戏

    A.需要掌握的 1.添加图片资源(暂时认为@2x跟非@2x代表同一张图片) 2.搭建UI界面* 文本标签* 4个按钮* 中间的图片 3.设置状态栏样式 4.监听下一题按钮的点击 5.延迟加载数据* 加 ...

  8. Android 解析 xml

    URL httpUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection )httpUrl.openConnection(); c ...

  9. 获取客户端Ip地址方法

    public static string GetIp() { string ip; HttpRequest request = HttpContext.Current.Request; if (req ...

  10. CSS链接、光标、DHTML、缩放

    个属性 18.2 CSS中光标的使用(更详细可看文档) 属性名称                属性值                说明 cursor                 auto    ...