iOS的事件分类
-
1 触摸事件(是开发中经常使用的事件)
- 只有继承
UIResponder
的对象才能处理事件
,对之做出响应,也称为响应者对象
-
UIApplication
,UIView
,UIViewController
都是继承UIResponder
,都可以处理事件
- 只有继承
-
2 加速计事件(摇一摇,跑步计数等)
-
3 远程控制事件(耳机切换歌曲)
触摸事件处理的的方法
- 开始触摸
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- 移动
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- 取消
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- 结束
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
UITouch触摸对象常用的方法和属性
- 方法
-1 - (CGPoint)locationInView:(nullable UIView *)view; 返回当前触摸对象的View的坐标点
-2 - (CGPoint)previousLocationInView:(nullable UIView *)view;返回当前触摸View的上一次的触摸点
- 属性
@property(nonatomic,readonly) NSTimeInterval timestamp;
@property(nonatomic,readonly) UITouchPhase phase;
@property(nonatomic,readonly) NSUInteger tapCount; // touch down within a certain point within a certain amount of time
@property(nonatomic,readonly) UITouchType type
demo例子(UIView的拖拽)
给控制器,添加一个子控件
UIView
,在UIView中实现 触摸事件的处理方法
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取到UITouch对象
UITouch *touch = [touches anyObject];
//当前的触摸点
CGPoint currentPoint = [touch locationInView:self];
//获取到上一次移动的触摸点
CGPoint prePoint = [touch previousLocationInView:self];
//移动的差值
CGFloat offsetX = currentPoint.x - prePoint.x;
CGFloat offsetY = currentPoint.y - prePoint.y;
//平移(transform), 在原来平移的基础上平移
self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY);
}
01_uiview的平移.gif
事件的传递
- 发生触摸事件之后,系统会将改事件加入到
UIApplication
管理的事件队列
中 -
UIApplication
会从事件队列中取出最前面的事件,并将改事件分发给keyWindow处理 - 主窗口(keyWindow)会在视图层中找到一个最合适的视图来处理这个事件
- 当找到
合适的View
控件之后,就会调用触摸事件的touches方法 做出相应的事件处理
02.png注意: 事件的传递的一层一层的,从父控件传递给子控件,如果父控件不能接受事件的传递,那么子控件也就不能接受触摸事件
当点击
绿色的View
事件的传递过程为
UIApplication
->UIWindow
->粉色View
->紫色View
->绿色View
- 不能接受事件的3中情况
//1.控件的属性,不可以交互的
userInteractionEnabled = no
//2.隐藏控件
hidden = yes
//3.透明度小于 0.01的控件
//上述的3中情况,不可以处理事件
寻找最合适的View处理事件
操作判断
- 1.判断是否可以处理事件
- 2.触摸点是否在自己身上
- 3.重后向前遍历,执行1,2的操作寻找子控件
- 4.如果没有,则自己就是最合适的view
需要实现的方法
//一个事件传递给这个View的时候,这个方法就会被调用
//返回的值,就是最合适的View
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
return [super hitTest:point withEvent:event];
}
//判断当前点是不是在自己身上
//当hitTest:withEvent:调用的时候,内部就会调用这个方法
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event{
return YES;
}
hitTest: withEvent:方法的内部原理实现
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
//内部实现方法
//1.判断是否可以接受事件
if (self.hidden == YES || self.alpha <= 0.01 || self.userInteractionEnabled == NO) {
return nil;
}
//2.判断触摸点是否在自己身上
if (![self pointInside:point withEvent:event]) {
return nil;
}
//3.从后向前遍历子控件
int count = (int)self.subviews.count;
for (int i = count - 1; i >= 0; i--) {
//获取到子控件
UIView *chiledView = self.subviews[i];
//转化坐标点 到子控件上
CGPoint childPoint = [self convertPoint:point toView:chiledView];
//获取View
UIView *fitView = [chiledView hitTest:childPoint withEvent:event];
//如果存在,就是最合适的view
if (fitView) {
return fitView;
}
}
//没有找到合适的View,返回自己
return self;
}
注意:如果在判断的时候是 子控件
需要转化子控件的 坐标点
网友评论