概念
UIEvent:
表示一个触摸事件(从第一个手指开始触摸屏幕到最后一个手指离开屏幕)一个UIevent包括多个UITouch对象组成,有几根手指就有几个touch对象。
属性:UIEventType
UIEventTypeTouches,//触摸
UIEventTypeMotion,//移动
UIEventTypeRemoteControl,//远程控制
UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),//有力度的按压
属性:allTouchs,表示所有UITouch的对象集合
UITouch
表示一个根手指的点击事件,能够表明当前手指的点击位置,状态(触碰,移动,离开)
- (CGPoint)locationInView:(nullable UIView *)view;//获取当前点击的点在view中坐标
- (CGPoint)previousLocationInView:(nullable UIView *)view//获取上个点击的点在view中坐标
UIResponder
在iOS中能够相应事件的对象都是UIResponder子类对象。UIResponder提供了四个供用户点击回调的方法(开始、移动、结束、取消),其中只有当程序强制退出、来电等意外情况中断时才对调用“取消”事件。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);
可以在UIResponder中重写上述方法来进行点击回调监听。
当多个视图叠加,手势又互有冲突时怎么判断哪个View处理哪个时间呢?
现在涉及到响应链的生成与处理。
响应链
响应链是由当前视图所有可以执行或响应触摸事件的UIResponder组成,是一个树形结构
- 响应链的形成:appdelegate->UIApplication-->UIWindow-->RootViewController-->RootViewController.view ......
- 响应事件的分发,从第一个UIWindow对象开始,先判断UIWindow是否合格,其次判断 点击位置在不在这个Window内,如果不在 ,返回nil, 就换下一个UIWindow;如果在的话,并且UIWindow没有subView就返回自己,整个过程结束。如果UIWindow有subViews,就从后往前遍历整个subViews,做和UIWindow类似的事情,直到找到一个View。如果没有找到到就不做传递。(合格的意思是:控件允许接收时间,1、不能被隐藏 2、alpha的值大于0.01 3、isUserInterface为YES,UILabel和UIImageView 默认是NO)
- 响应事件的判断:通过分发找到的view在调用
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
来判断是否由哪个view处理。
//模拟系统判断
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event {
//判断是否合格
if (!self.hidden && self.alpha > 0.01 && self.isUserInteractionEnabled) {
//判断点击位置是否在自己区域内部
if ([self pointInside: point withEvent:event]) {
UIView *attachedView;
for (int i = self.subviews.count - 1; i >= 0; i--) {
UIView *view = self.subviews[i];
//对子view进行hitTest
attachedView = [view hitTest:point withEvent:event];
if (attachedView)
break;
}
if (attachedView) {
return attachedView;
} else {
return self;
}
}
}
returnnil;
}