什么是事件分发机制,当用户触碰屏幕后,其事件的传递过程被称作事件的分发,IOS的事件分发机制大致原理与Android及其相似。该事件传递过程往往都是由父控件一步一步向其子控件进行分发的。

事件分类


在Ios中事件被分为了3类:

  • 触摸事件:手指触碰屏幕时触发的事件。
  • 加速事件:当手机加速度改变时触发的时间(列如摇一摇)。
  • 远程控制事件:当用户使用远程遥控设备时触发的事件。

哪些View可以响应事件


继承自UIResponder的类都可以响应事件的分发。所以UIApplication,UIView,UIViewController以及它们的子类均可以响应事件的分发和处理。

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;
//3D触碰时触发
- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);

加速事件:

//开始加速时触发
- (void)motionBegan:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
//结束加速时触发
- (void)motionEnded:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
//加速取消时触发
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);

远程遥控事件:

//远程遥控事件触发
- (void)remoteControlReceivedWithEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(4_0);

UITouch


什么是UITouch,我们可以将其想象成于手指相关联的一个对象,往往会被用来处理多点触碰,当一只手指触碰屏幕是,就会有一个UITouch对象返回,当有多只手指触碰屏幕时,就会有多个UITouch对象返回,它们是通过List来存储的。

UITouch的重要属性:

//当前触碰点所在window
@property(nullable,nonatomic,readonly,strong) UIWindow *window;
//当前触碰点所在视图
@property(nullable,nonatomic,readonly,strong) UIView *view;
//短时间内点击屏幕的次数
@property(nonatomic,readonly) NSUInteger tapCount;
//事件发生所用时间
@property(nonatomic,readonly) NSTimeInterval timestamp;
//当前触碰状态(枚举类)
@property(nonatomic,readonly) UITouchPhase  phase;
//触碰类型(枚举类)
@property(nonatomic,readonly) UITouchType type;
//手指与屏幕的接触半径
@property(nonatomic,readonly) CGFloat majorRadius;
//手指与屏幕的接触半径误差值
@property(nonatomic,readonly) CGFloat majorRadiusTolerance;
//获取屏幕手势
@property(nullable,nonatomic,readonly,copy)NSArray <UIGestureRecognizer *> *gestureRecognizers;
//触碰屏幕的压力值(通常为1)
@property(nonatomic,readonly) CGFloat force;
//最大压力值
@property(nonatomic,readonly) CGFloat maximumPossibleForce;

UITouch的重要方法:

//返回当前触碰的视图
- (CGPoint)locationInView:(nullable UIView *)view;
//返回前一个触碰点的视图
- (CGPoint)previousLocationInView:(nullable UIView *)view;
//当前触碰视图所在的视图(父视图)
- (CGPoint)preciseLocationInView:(nullable UIView *)view;
//前一个触碰视图所在的视图(父视图)
- (CGPoint)precisePreviousLocationInView:(nullable UIView *)view;

事件分发机制(hitTest)


  Ios事件分发,是从window开始向其子控件传递,其子控件又作为父控件向子控件进行分发的,如果子控件可以处理该事件则该事件有子控件处理,如果所有子控件无法处理该事件,则该事件会交由父控件处理。例如下图:如果我们点击了绿色View,该事件将会由Controller开始向内分发经过红色->蓝色->绿色,然后绿色View处理该事件,该过程的本质就是找到一个最适合处理该事件的View。 那么源码中是怎么实现这一过程的呢?hitTest方法和pointInside方法来共同实现寻找最适合处理该事件的View,所有的View都含有这两个方法,pointInside方法在hitTest方法中被调用,用于判断触碰点是否在该View内返回YES或者NO,而hitTest方法的则就是寻找最适合View的本质方法,其返回值为View

hitTest方法做了什么


  • 判断当前View能否响应事件
  • 触碰点是否在该View内部
  • 从后往前遍历所有子控件判断子控件是否更合适响应该事件
  • 如果没有合适的子控件来响应事件,则交给该View本身来处理事件

模拟hitTest内部实现

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {//判断自己能否响应事件if(self.userInteractionEnabled == NO||self.hidden == YES|| self.alpha <= 0.01){return nil;}//2.判断当前点在不在该View内部if(![self pointInside:point withEvent:event]){return nil;}//3.从后往前遍历自己的子控件,让子控件执行其hitTest方法for(UIView view in self.subviews){//将点切换为子view坐标系上的点CGPoint childPoint =[self convertPoint:point toView:view];UIView fitView = [view hitTest:childPoint withEvent:event];if(fitView){return fitView;}}return self;
}

哪些视图无法处理事件

  • 当userInteractionEnabled = NO时无法处理事件(如果父视图的userInteractionEnabled=NO,则子视图同样无法处理事件)
  • 当View被隐藏时无法处理事件(当父视图被隐藏时,其子视图也会被隐藏)
  • 当alpha值为0.0 ~ 0.01时无法处理事件(同样如果父视图alpha值为0.0 ~ 0.01,子视图也无法处理事件)

iOS 事件分类及事件分发机制相关推荐

  1. 自定义View(二)--表层浅析View的事件分发机制和滑动冲突

    转载请注明出处:From李诗雨:http://blog.csdn.net/cjm2484836553/article/details/54387722 不诗意的女程序猿不是好厨师~ 这篇文章来得有些曲 ...

  2. iOS开发事件分发机制—响应链—手势影响

    1.提纲 什么是iOS的事件分发机制 ? 一个事件UIEvent又是如何响应的? 手势对于响应链有何影响? 2.事件分发机制 2.1.来源 以直接触摸事件为例: 当用户一个手指触摸屏幕是会生成一个UI ...

  3. 事件分发机制并不是洪水猛兽

    文章目录 OnTouchListener与OnClickListener的优先级 事件分发 滑动冲突 处理滑动冲突 1. 内部拦截法 2.外部拦截法 当MotionEvent产生后,系统总归要将其传递 ...

  4. Android开发指南!Android事件分发机制收藏这一篇就够了,2年以上经验必看

    前言 现在的终端开发已经开始进入稳定期,在这个阶段大厂压力很大小厂更会收到挤压,人们使用的App越来越固定,即使是大厂,几年前平台级应用发个Push就能引流几十万,现在这些的作用也越来越小,特别到了今 ...

  5. Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

    <div id="container">         <div id="header">     <div class=&qu ...

  6. View事件分发机制(源码 API27)

    1.什么是事件分发机制 当用户触摸屏幕时,会产生一个touch事件,这个touch事件(motionEvent)传递到某个具体的view处理的整个过程 用户触摸屏幕会产生一个事件流(ACTION_DO ...

  7. Android事件分发机制详解

    2019独角兽企业重金招聘Python工程师标准>>> 之前在学习Android事件方法机制的时候,看过不少文章,但是大部分都讲的不是很清楚,我自己理解的也是云里雾里,也尝试过阅读源 ...

  8. android触摸事件分发,Android 事件分发机制

    Android 事件分发机制一直让人头痛,之前也是面向 GitHub 编程得过且过.今天下定决心了解一下,以便后面自己定制 View 效果.Android 触摸事件有三个基本类型:ACTION_DOW ...

  9. View事件分发机制(源码分析篇)

    01.Android中事件分发顺序 1.1 事件分发的对象是谁 事件分发的对象是事件.注意,事件分发是向下传递的,也就是父到子的顺序. 当用户触摸屏幕时(View或ViewGroup派生的控件),将产 ...

最新文章

  1. AI一分钟|阿里成立“罗汉堂”;vivo微信人脸识别支付下半年商用
  2. 18秋c语言程序设计作业答案,[四川大学]《C语言程序设计0008》19秋在线作业2
  3. c++11-std::functionbind
  4. debugging Auto Layout:Logical Errors
  5. 腾讯三面:40亿个QQ号码如何去重?
  6. LINUX 文件合并,去重
  7. 现实中简单配置路由器
  8. 二叉搜索树(二叉排序树)
  9. 穆迪将收购信用数据和见解领导者Cortera
  10. vue第五天笔记02——vuex数据仓库
  11. Qt系列文章之 QAbstractItemModel(下)
  12. 惠普HP compaq康柏系列 CQ40笔记本电脑拆机除尘
  13. WordPress活动日历和预订插件指南
  14. php 红包过期退回,RabbitMQ功能实现1- 红包未领取退回
  15. 日本护照持有者可以免签进入全球193个目的地,创下历史记录
  16. 不同试验设计遗传力的计算方法
  17. 用soapUI测试GET/POST接口
  18. 中国幼儿教育市场运营模式与未来发展方向分析报告2022版
  19. 【重点警惕】.locked1后缀--TellYouThePass勒索病毒家族旗下勒索病毒
  20. 备考第3天:RHEL7 系统安装与基本调试

热门文章

  1. 联想台式修复计算机,联想台式电脑如何一键恢复出厂设置
  2. nginx安装crt证书
  3. 全网最全抖音运营攻略
  4. 【系统分析师之路】第六章 多媒体基础知识
  5. 二分法求多项式单根 — c语言
  6. 君澜入驻上饶,打造动物主题休闲度假体验
  7. K8S 快速入门(十六)实战篇:StorageClass(存储类)
  8. 自己用html + js 一百行代码做一个朗读器
  9. 【精品】手绘插画怎么学?
  10. python列表输出学生姓名学号链表_1. 建立一个学生信息的循环链表,每个节点里面包含了学生学号、姓名、籍贯三个信息。通过遍历,输出链表...