传递链
UIApplication -> UIWindow -> UIView -> initial view,以上就是事件的传递,也就是寻找最合适的view的过程。
响应链
传递链反过来
寻找合适的View
两个重要的方法:
hitTest:withEvent:方法
pointInside方法
不响应的前置条件 不会调用hitTest
-
不允许交互:userInteractionEnabled = NO
-
隐藏:如果把父控件隐藏,那么子控件也会隐藏,隐藏的控件不能接受事件
-
透明度:如果设置一个控件的透明度<0.01,会直接影响子控件的透明度。alpha:0.0~0.01为透明。
-
子视图超出父视图的情况
Note:默认UIImageView不能接受触摸事件,因为不允许交互,即userInteractionEnabled = NO,所以如果希望UIImageView可以交互,需要userInteractionEnabled = YES。
应用
- 子View超出superView后,仍然响应点击,相关解决方案
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// toView 重在后参数,把point转换成toView参数代表的View之上的坐标
// fromView 重在调用者 把point转换成调用View之上的坐标
CGPoint point1= [self convertPoint:point toView:self];
CGPoint point2= [self.superview convertPoint:point fromView:self];
for (UIView *view in self.subviews) {
// 把当前point转换为子View所在的point
CGPoint viewP = [self convertPoint:point toView:view];
// 判断转换后的点是否在子View之内
if ([view pointInside:viewP withEvent:event]) {
return view;
}
}
return [super hitTest:point withEvent:event];
}
- 子View不响应,直接透传给superView
userInteractionEnabled = NO
- 子View响应后,superView仍然响应
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
// 1.自己先处理事件...
NSLog(@"do somthing...");
// 2.再调用系统的默认做法,再把事件交给上一个响应者处理
[super touchesBegan:touches withEvent:event];
}
One More Thing
当一个触摸事件发生后首先是由IOKit.framework 生成一个 IOHIDEvent 事件并由 SpringBoard 接收,然后SpringBoard会通过match port将事件转发给我们是App进程,然后触发App注册在RunLoop中的Source1来处理事件,Source1会触发__IOHIDEventSystemClientQueueCallback回调,回调后又会触发Source0,再后面就是UIApplication从事件队列取出事件派发
网友评论