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

*当用户点击屏幕时,会产生一个触摸事件,系统会将触摸事件加入到 UIApplication管理事件队里中

*UIApplication 会从事件队列中取出最前面的事件进行分发以便处理,通常,先发送事件给应用程序主窗口(UIwindow0

*主窗口会调用 hitTest:withEvent:方法在视图(UIView)层次结构中找到一个最合适的 UIView来处理触摸事件

(hitTest:LwithEvent:其实是 UIView 的一个方法UIWindow 继承自 UIView,因此主窗口UIWinow 也是属于视图的一种)

hitTest:withEvent:处理流程大致是这样的:

首先调用当前视图的 pointInside:withEvent:方法判断触摸点是否在当前视图内:

若 pointInside:withEvent:返回 NO, 说明触摸点不在当前视图内,,则当前的 hitTest:withEvent:返回 nil

若 pointInside:withEvent: 返回 YES, 说明触摸点在当前视图内,则遍历其所有子视图(subviews),调用子视图的 hitTest:withEvent: 方法重复前面的步骤,子视图遍历的顺序是从 top 到 bottom, 即从 subviews 数组的末尾向前遍历,直到有子视图的 hitTest:withEvent: 方法返回非空对象或者全部子视图遍历完毕

? 若第一次有子视图的hitTest:withEvent:方法返回非空对象,则当前视图的hitTest:withEvent:方法就返回此对象,处理结束

? 若所有子视图的hitTest:withEvent:方法都返回nil,则当前视图的hitTest:withEvent:方法返回当前视图自身(self)

• 最终,这个触摸事件交给主窗口的hitTest:withEvent:方法返回的视图对象去处理

我大致画了个iOS触摸事件分发的原理图:

• hitTest:withEvent:方法会忽略以下视图:

1> 隐藏(hidden=YES)的视图

2> 禁止用户操作(userInteractionEnabled=NO)的视图

3> alpha<0.01的视图

4> 如果一个子视图的区域超过父视图的区域(如果父视图的clipsToBounds属性为NO,超过父视图区域的子视图内容也会显示),那么正常情况下在父 视图区域外的触摸操作不会被识别,因为父视图的pointInside:withEvent:方法会返回NO,这样就不会继续向下遍历子视图了。当然,也 可以重写pointInside:withEvent:方法来处理这种

    引自http://www.cnblogs.com/mjios/archive/2013/03/06/2945347.html

时间: 2024-10-20 10:06:42

消息点击事件的响应链---hitTest:withEvent:方法的相关文章

事件分发&amp;响应链

iOS的三种事件:触摸事件/运动事件/远程控制事件 [objc] view plaincopy typedef enum { UIEventTypeTouches, UIEventTypeMotion, UIEventTypeRemoteControl, } UIEventType; 只有继承UIResponder类的对象才能处理事件,如UIView.UIViewController.UIApplication都继承自UIResponder,都能接收并处理事件.UIResponder中定义了上面

iOS学习9_事件分发&amp;响应链&amp;android转iOS的感悟

iOS的三种事件:触摸事件/运动事件/远程控制事件 typedef enum { UIEventTypeTouches, UIEventTypeMotion, UIEventTypeRemoteControl, } UIEventType; 只有继承UIResponder类的对象才能处理事件,如UIView.UIViewController.UIApplication都继承自UIResponder,都能接收并处理事件.UIResponder中定义了上面三类事件相关的处理方法: 下面主要讨论触摸事

iOS开发 - 事件传递响应链

一.序言 当我们在使用微信等工具,点击扫一扫,就能打开二维码扫描视图.在我们点击屏幕的时候,iphone OS获取到了用户进行了"单击"这一行为,操作系统把包含这些点击事件的信息包装成UITouch和UIEvent形式的实例,然后找到当前运行的程序,逐级寻找能够响应这个事件的对象,直到没有响应者响应.这一寻找的过程,被称作事件的响应链,如下图所示,不用的响应者以链式的方式寻找. 事件响应链: 二.响应者 在iOS中,能够响应事件的对象都是UIResponder的子类对象.UIRespo

ios中事件的响应链(Responder chain)和传递链

事件的响应链涉及到的一些概念 UIResponder类,是UIKIT中一个用于处理事件响应的基类.窗又上的所有事件触发,都由该类响应(即事件处理入又).所以,窗又上的View及控制器都是 派生于该类的,例如UIView.UIViewController等. 调用UIResponder类提供的方法或属性,我们就可以捕捉到窗又上的所有响应 事件,并进行处理. 响应者链条是由多个响应者对象连接起来的链条,其中响应者对象是能处理事 件的对象,所有的View和ViewController都是响应者对象,利

cceditbox和cocostudio联合界面点击事件无响应问题,Android中创建文件夹问题

这两个问题折腾了我一天多时间,尽快下班时候把创建文件夹问题给解决了,刚把cceditbox点击事件无响应问题解决了.真是大爽. 1.创建文件夹 _mkdir()这个c函数就行,在vs ide中,定位的头文件是direct.h,但是这个文件不被ndk编译通过,没有这个文件.好吧,死脑筋,开始怀疑eclipse库路径设置有问题,但是不知道哪不对,搜索到了头大地步,好吧,认真仔细一看,原来是在ndk中,_mkdir函数放在了#include <sys/stat.h>中,改为这个头文件就行了. 2.点

ListView使用自定义适配器的情况下实现适配器的控件点击事件执行Activity界面中的方法

如果ListView使用的是自定义的适配器,比如MyArrayAdapter extends ArrayAdapter<String> 那么,如何实现适配器中的点击事件执行activity界面中的方法呢? 实现思路:在自定义适配器MyArrayAdapter 类型中自定义接口和接口方法,然后在activity界面中MyArrayAdapter实例实现这个接口. 较为完整的代码见上文. 1.MyArrayAdapter 关键代码 自定义接口和方法的代码如下: //列表项的单击事件监听接口 pub

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

闲来无事 观摩别人的项目 常常发现对UIView的hitTest:withEvent:方法的重写,以前也查过这个方法的用法作用,但是时间一长又忘记了.今天再次看到,就记录一下. 用户触摸屏幕后事件的传递过程 当用户点击屏幕后,UIApplication先响应事件,然后传递给UIWindow.如果window可以响应.就开始遍历window的subViews.遍历的过程中,如果第一个遍历的View1可以响应,那就遍历View1的SubViews.(依次这样不停地查找,直至查找到合适的响应事件vie

iOS 事件传递响应链

iOS中加载的时候会先执行main函数 int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } 根据main函数的参数加载UIApplication->AppDelegate->UIWindow->UIViewController->superView-&g

Unity3D开发之NGUI点击事件穿透响应处理

http://www.xuebuyuan.com/1936292.html 在使用NGUI 开发2D项目的时候,发现了一个问题,就是如果点出一个菜单,然后点击菜单上面的按钮的时候就会使得按钮下面的物品也会触发点击事件(如果有的话), 经过查阅相关资料,发现了一个很方便的处理方法:分层处理.就是把菜单层和游戏显示层分为不同的Layer:比如: 和 然后,在NGUI的UICamera的脚本那里,设定它的事件响应: 这样的话,他就会响应到相应的层了,当然还可以更灵活地去用代码控制设定使用,这里只是一个