iOS Hit-Testing事件响应链
2016-06-06 21:19
357 查看
iOS Hit-Testing事件响应链
官方文档Understanding Event Handling, Responders, and the Responder Chain中,有这样的叙述:app使用响应者对象接收和处理事件。响应者对象是
UIResponder类的实例,常见的子类包括
UIView,
UIViewController和
UIApplication。响应者接收原始事件数据,并且必须处理该事件或将其转发给另一个响应者对象。当你的app收到一个事件时,
UIKit会自动将该事件指向最合适的响应者对象,称为第一响应者(first responder)。
未被处理的事件会从响应者传递到活动的响应者链(active responder chain)中的响应者,响应者链是应用程序的响应者对象的动态配置(Unhandled events are passed from responder to responder in the active responder chain, which is a dynamic configuration of your app’s responder objects)
在你的app中没有单个响应者链。
UIKit为对象如何从一个响应者传递到另一个响应者定义了默认的规则,但是你可以通过覆盖响应者对象中相应的属性来改变这些规则。
下图显示了一个应用程序中默认的响应者链,其接口包含label,text field,一个button和两个背景 view。如果text field不处理事件,则UIKit将该事件发送到文本字段的父级
UIView对象,然后是该window的根view。在根view中,响应者链在将事件引导到window之前转移到拥有该view的view controller。如果窗口不处理事件,则UIKit将事件传递给
UIApplication对象,如果该对象是
UIResponder的实例并且已经不是响应者链的一部分,则可能传递给app delegate。
对于每种类型的事件,
UIKit都会指定一个第一响应者,并首先将该事件发送给该对象。 第一响应者根据事件的类型而变化。
Touch events
第一响应者是触摸发生的view
Press events
第一个响应者是焦点的响应者
Shake-motion events
第一个响应者是你(或者UIKit)指定的第一个响应者
Remote-control events
第一个响应者是你(或者UIKit)指定的第一个响应者
Editing menu messages
第一个响应者是你(或者UIKit)指定的第一个响应者
Controls使用action消息直接与其关联的目标对象进行通信。 当用户与控件进行交互时,控件调用其目标对象的动作方法 - 换句话说,它向其目标对象发送一个动作消息。 Action消息不是事件,但它们仍然可以利用响应者链。 当控件的目标对象为
nil时,UIKit从目标对象开始,遍历响应者链,直到找到实现相应操作方法的对象。 例如,UIKit编辑菜单使用此行为来搜索响应者对象,这些对象实现了名称为
cut(_ :),
copy(_ :)或
paste(_ :)的方法
如果view附加有的gesture recognizer,则gesture recognizer在view接收之前接收touch和press事件。 如果view的所有的gesture recognizer都无法识别其手势,则将事件传递给view进行处理。 如果view不处理它们,则UIKit将事件传递给响应者链。 有关使用手势识别器处理事件的更多信息,请参阅处理UIKit手势。
确定哪个响应者包含触摸事件
UIKit使用基于视图的hit-testing来确定触摸事件发生的位置。 具体来说,
UIKit将触摸位置与视图层次结构中视图对象的边界进行比较。
UIView的
hitTest(_:with :)方法遍历视图层次结构,查找包含指定触摸的最深的子视图。 该view成为触摸事件的第一响应者。
注意
如果触摸位置超出view边界,则
hitTest(_:with :)方法会忽略该view及其所有子view。 因此,当一个视图的
clipsToBounds属性为
false时,即使这些子视图碰巧包含触摸,也不会返回该view边界外的子视图。
UIKit将每个触摸永久分配给包含它的视图。
UIKit在触摸第一次出现时创建每个
UITouch对象,并且只有在触摸结束后才释放该触摸对象。 随着触摸位置或其他参数的更改,
UIKit会使用新信息更新
UITouch对象。 唯一不变的属性是包含视图(containing view)。 即使触摸位置移动到原始视图之外,触摸视图属性中的值也不会改变。
hitTest(_:with:)
hitTest(_:with:)返回包含指定点receiver的视图层级(包括它本身)中的最深的后代。(Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point.)
此方法通过遍历视图层级,调用每个子视图的
point(inside:with:)方法来确定哪个子视图应该接收触摸事件。如果
point(inside:with:)返回
true,那么类似的遍历子视图的视图层次,直到找到包含指定点的最前面的view。如果视图不包含该点,则该视图层级的分支将被忽略。
此方法忽略隐藏的视图对象、禁用了用户交互,或者alpha级别小于0.01的view
如下的例子,button是有颜色的view的子view,但是button在view的边界之外,此时点击button,并不会响应button的事件
可以这样重写
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法,来使button响应action事件:
重写有颜色view的
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *view = [super hitTest:point withEvent:event]; if (view) { return view; } for (UIView *subView in self.subviews) { CGPoint cPoint = [self convertPoint:point toView:subView]; if ([subView hitTest:cPoint withEvent:event]) { return subView; } } return nil; }
其它应用包括:
参考:
iOS事件响应链中Hit-Test View的应用
Hit-Testing in iOS
iOS hitTest-点击事件分发分析
1.扩大响应的区域
2.将触摸事件传递给下面的视图
3.将触摸事件传递给子视图
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- 讲解iOS开发中基本的定位功能实现
- iOS中定位当前位置坐标及转换为火星坐标的方法
- js判断客户端是iOS还是Android等移动终端的方法
- iOS应用开发中AFNetworking库的常用HTTP操作方法小结
- iOS应用中UISearchDisplayController搜索效果的用法
- IOS开发环境windows化攻略
- iOS应用中UITableView左滑自定义选项及批量删除的实现
- iOS中UIAlertView警告框组件的使用教程
- 浅析iOS应用开发中线程间的通信与线程安全问题
- 检测iOS设备是否越狱的方法
- .net平台推送ios消息的实现方法
- 探讨Android与iOS,我们将何去何从?
- Android、iOS和Windows Phone中的推送技术详解