此方法可实现点击穿透、点击下层视图功能

一. hitTest:withEvent:调用过程

iOS系统检测到手指触摸(Touch)操作时会将其放入当前活动Application的事件队列,UIApplication会 从事件队列中取出触摸事件并传递给key window(当前接收用户事件的窗口)处理,window对象首先会使用hitTest:withEvent:方法寻找此次Touch操作初始点所在的 视图(View),即需要将触摸事件传递给其处理的视图,称之为hit-test view。

window对象会在首先在view hierarchy的顶级view上调用hitTest:withEvent:,此方法会在视图层级结构中的每个视图上调用pointInside:withEvent:,如果pointInside:withEvent:返回YES,则继续逐级调用,直到找到touch操作发生的位置,这个视图也就是hit-test view。

hitTest:withEvent:方法的处理流程如下:

  1. 首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;
  2. 若返回NO,则hitTest:withEvent:返回nil;
  3. 若返回YES,则向当前视图的所有子视图(subviews)发送hitTest:withEvent:消息,所有子视图的遍历顺序是从top到bottom,即从subviews数组的末尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕;
  4. 若第一次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;
  5. 如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。

hitTest:withEvent:方法忽略隐藏(hidden=YES)的视图,禁止用户操作(userInteractionEnabled=YES)的视图,以及alpha级别小于0.01(alpha<0.01)的视图。如果一个子视图的区域超过父视图的bound区域(父视图的clipsToBounds 属 性为NO,这样超过父视图bound区域的子视图内容也会显示),那么正常情况下对子视图在父视图之外区域的触摸操作不会被识别,因为父视图的 pointInside:withEvent:方法会返回NO,这样就不会继续向下遍历子视图了。当然,也可以重写 pointInside:withEvent:方法来处理这种情况。

对于每个触摸操作都会有一个UITouch对 象,UITouch对象用来表示一个触摸操作,即一个手指在屏幕上按下、移动、离开的整个过程。UITouch对象在触摸操作的过程中在不断变化,所以在 使用UITouch对象时,不能直接retain,而需要使用其他手段存储UITouch的内部信息。UITouch对象有一个view属性,表示此触摸操作初始发生所在的视图,即上面检测到的hit-test view,此属性在UITouch的生命周期不再改变,即使触摸操作后续移动到其他视图之上。

二.定制hitTest:withEvent:方法

如果父视图需要对对哪个子视图可以响应触摸事件做特殊控制,则可以重写hitTest:withEvent:pointInside:withEvent:方法。

这里有几个例子:


  1. 此例子中button,scrollview同为topView的子视图,但scrollview覆盖在button之上,这样在在button上的触摸
    操作返回的hit-test
    view为scrollview,button无法响应,可以修改topView的hitTest:withEvent:方法如下:

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *result = [super hitTest:point withEvent:event];
    CGPoint buttonPoint = [underButton convertPoint:point fromView:self];
    if ([underButton pointInside:buttonPoint withEvent:event]) {
    return underButton;
    }
    return result;
    }

    这样如果触摸点在button的范围内,返回hittestView为button,从button按钮可以响应点击事件。

  2. 网上的一个案例:

convertPoint:toView:

  转换一个点从接收者坐标系到给定的视图坐标系

  - (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view

  参数

  point

  一个在调用者坐标系中的点

  view

  一个包含了需要被转换的点的视图。如果视图是nil,那么这个方法将会转换成基于窗口的坐标。否则视图和接收者都要属于同一个UIWindow对象。

  返回值

  基于视图的坐标系转换过的点

hitTest:withEvent:方法(此方法可实现点击穿透、点击下层视图功能)的更多相关文章

  1. hitTest:withEvent:方法流程

    此方法可实现点击穿透.点击下层视图功能. 一. hitTest:withEvent:调用过程 iOS系统检测到手指触摸(Touch)操作时会将其放入当前活动Application的事件队列,UIApp ...

  2. 消息点击事件的响应链---hitTest:withEvent:方法

    *当用户点击屏幕时,会产生一个触摸事件,系统会将触摸事件加入到 UIApplication管理事件队里中 *UIApplication 会从事件队列中取出最前面的事件进行分发以便处理,通常,先发送事件 ...

  3. 响应者链 hittest:withEvent: 方法的使用

    关于响应者链部分的基础内容 参考http://www.cnblogs.com/wendingding/p/3795171.html 这里我要说明的是 关于- (UIView *)hitTest:(CG ...

  4. 关于UIView的hitTest:withEvent:方法的理解

    闲来无事 观摩别人的项目 常常发现对UIView的hitTest:withEvent:方法的重写,以前也查过这个方法的用法作用,但是时间一长又忘记了.今天再次看到,就记录一下. 用户触摸屏幕后事件的传 ...

  5. UITableView/UIScrollView 不能响应TouchBegin 的处理 及窥见 hitTest:withEvent:

    重写touchBegin 方法是不行的,在UITableView/UIScrollView 解决方案 重写hitTest:withEvent:  在他们的子类中 - (UIView *)hitTest ...

  6. 点击事件处理, 以及hitTest:withEvent:实现

    发送触摸事件后, 系统会将事件添加到系统UIApplication的事件管理队列中 UIApplication会在事件队列的最前端取出事件,然后分发下去,以便处理, 通常会把事件首先分发给KeyWin ...

  7. .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]

    方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...

  8. paip。java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型

    paip.java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型 作者Attilax 艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http ...

  9. JavaScript【面向对象】-静态方法-私有方法-公有方法-特权方法

    JavaScript面向对象是近年来比较火的一个概念了,由于小弟才疏学浅,虽然做过不少的web项目,看了网上很多深奥的资料和教程,还是对他们深奥 的理论一知半解,前段时间看了点书,总算有了自己的理解, ...

随机推荐

  1. HDU 5904 - LCIS (BestCoder Round #87)

    HDU 5904 - LCIS [ DP ]    BestCoder Round #87 题意: 给定两个序列,求它们的最长公共递增子序列的长度, 并且这个子序列的值是连续的 分析: 状态转移方程式 ...

  2. python yield 理解

    在别人的代码中看到yield这个关键字,看了几篇资料,说一下个人理解. 包含yield 关键字的函数成为一个迭代器,yield跟return的位置一样,只不过每次返回结果后,并没有退出,而是等待下一次 ...

  3. [HDU] 2094 产生冠军(拓扑排序+map)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2094 注意每组数据处理前,map要清空. #include<cstdio> #includ ...

  4. [UVA] 784 - Maze Exploration

      Maze Exploration  A maze of rectangular rooms is represented on a two dimensional grid as illustra ...

  5. 去掉Eclipse打开后定期弹出Usage Data Upload对话框

    Eclipse 的 UDC 老定期蹦出来说要上传使用数据到 eclipse 官网服务器去除方法: 1.删除 eclipse/plugins 目录下以 org.eclipse.epp.usagedata ...

  6. 解决PopupWindow遮住输入法

    1: PopupWindow中的设置 pop.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); pop.setSoftInputMode(Win ...

  7. 《Programming WPF》翻译 第7章 5.可视化层编程

    原文:<Programming WPF>翻译 第7章 5.可视化层编程 形状元素能提供一种便利的方式与图形一起工作,在一些情形中,添加表示绘图的元素到UI树中,可能是比它的价值更加麻烦.你 ...

  8. VBS 操作注册表 十六进制

    使用VBS操作注册表,通常使用RegRead/RegWrite/RegDelete方法,如: RegRead: 'read.vbs(将以下代码存为read.vbs文件) Dim OperationRe ...

  9. jsp验证码 (通过单击验证码或超链接换验证码)

    #code.jsp <%@ page language="java" import="java.util.*" import="java.awt ...

  10. Spark机器学习笔记一

    Spark机器学习库现支持两种接口的API:RDD-based和DataFrame-based,Spark官方网站上说,RDD-based APIs在2.0后进入维护模式,主要的机器学习API是spa ...