内容简介:在讲述UI事件传递之前,先要知道UIView 和 UILayer的区别是什么.简而言之事件的传递主要和两个方法有关接下来来看看这个流程图
在讲述UI事件传递之前,先要知道UIView 和 UILayer的区别是什么.简而言之
- UIView为其提供内容,以及负责处理触摸等事件,参与响应链
- CALayer负责显示内容contents UIView只负责事件传递和视图响应链,而显示部分的内容都是由CALayer来负责, 这提现了系统设计UIView和CALayer中所运用的一个设计原则,就是单一职责原则.
接下来看看这幅图
- 思考一下,当点击图中白圈那个位置的时候,事件是如何进行传递的呢.
事件的传递主要和两个方法有关
// 返回哪个视图响应这个事件,返回nil表示不处理该事件 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event // 判断某一个点击的位置是否在视图范围内 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 复制代码
接下来来看看这个流程图
首先,先判断视图的用户交互是否打开、是否隐藏、透明度是否大于0.01,如果有一个不符合,那么该视图将不处理任何事件响应,也不会进行后续的操作了.如果这三个条件都满足了,就会调用当前视图的 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 方法来判断点击的点是否在当前视图范围内,如果不在的话也会返回nil再由它当前视图的父视图去遍历它的同级兄弟视图,调用对应的 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法.如果当前视图的 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 返回YES,那么就会以倒叙的方式遍历当前视图的子视图,遍历的过程中会调用所有自视图的 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法,如果某个子视图返回了最终的事件响应视图的话,就会把对应的视图作为最终的响应视图返回给调用方,如果返回的是nil的话就会继续遍历当前视图的下一个子视图.如果全部遍历完了之后都没有对应的子视图去响应事件的话,由于当前点击位置在当前视图范围内,就会把当前的视图作为响应视图返回给调用方.
通过一个例子来更深入的理解一下
在下图这个正方形按钮中,只有白色圆型区域可以响应点击事件.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 和
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
方法来实现上诉功能.
#import "CustomButton.h"
@implementation CustomButton
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if (!self.userInteractionEnabled ||
[self isHidden] ||
self.alpha <= 0.01) {
return nil;
}
// 如果点击区域在白色圆形区域内,则返回self,否则不响应事件
if ([self pointInside:point withEvent:event]) {
return self;
}
else{
return nil;
}
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
CGFloat x1 = point.x;
CGFloat y1 = point.y;
CGFloat x2 = self.frame.size.width / 2;
CGFloat y2 = self.frame.size.height / 2;
// 这就是传说中的勾股定理
double dis = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
if (dis <= self.frame.size.width / 2) {
return YES;
}
else{
return NO;
}
}
@end
复制代码
好了,现在这个自定义的button就实现了上述的功能了. 回到最开始的问题,点击那个白色位置,事件是如何进行传递的呢.如下图:
首先点击位置在C2、B2、和A区域内,那么这3个视图都是有可能响应事件的.如果C2是B2的子视图,B2是A的子视图的话,那么按照顺序应该先调用子视图的 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法,而如果他们三个视图是平级的话,按照同级视图倒叙遍历的方式,也是C2先响应(因为C2覆盖在B2和A上).所以顺序就是C2先执行 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法如果返回nil,B2再执行,最后才是A.如果都没有处理这个事件,那么最后会传到UIApplication,如果仍然没有处理这个事件,那么最后就会忽略这个事件.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
大型分布式网站架构设计与实践
陈康贤 / 电子工业出版社 / 2014-9-1 / 79.00元
《大型分布式网站架构设计与实践》主要介绍了大型分布式网站架构所涉及的一些技术细节,包括SOA架构的实现、互联网安全架构、构建分布式网站所依赖的基础设施、系统稳定性保障和海量数据分析等内容;深入地讲述了大型分布式网站架构设计的核心原理,并通过一些架构设计的典型案例,帮助读者了解大型分布式网站设计的一些常见场景及遇到的问题。 作者结合自己在阿里巴巴及淘宝网的实际工作经历展开论述。《大型分布式网站......一起来看看 《大型分布式网站架构设计与实践》 这本书的介绍吧!