Android面试必问之触摸事件传递机制

一、Activity的构成

一个Activity包含了一个Window对象,这个对象是由PhoneWindow来实现的。PhoneWindow将DecorView作为整个应用窗口的根View,而这个DecorView又将屏幕划分为两个区域:一个是TitleView,另一个是ContentView,而我们平时所写的就是展示在ContentView中的。
在这里插入图片描述

二、触摸事件的类型

MotionEvent类,主要有三种事件类型:

  • ACTION_DOWN
  • ACTION_MOVE
  • ACTION_UP

三、事件传递的三个阶段

  • dispatchTouchEvent(分发):返回true表示事件被当前视图消费,返回super.dispatchTouchEvent表示继续分发事件
  • onInterceptTouchEvent(拦截):返回true表示拦截事件并调用onTouchEvent方法消费;返回false表示不拦截,继续传递给子视图。如果return super.onInterceptTouchEvent,分情况:
    在这里插入图片描述
  • onTouchEvent(消费):返回true表示当前视图处理该事件,返回false表示当前视图不处理事件,传递给父视图的onTouchEvent处理。如果return super.onTouchEvent,分情况:
    在这里插入图片描述
    ps:在Android系统中,拥有事件传递能力的类有:
      1. Activity:拥有分发和消费两个方法
      2. ViewGroup:拥有分发、拦截和消费三个方法
      3. View:拥有分发、消费两个方法

Activity对点击事件的分发过程

我们对触摸屏进行操作时,Linux就会收到相应的硬件中断,然后将中断加工成原始的输入事件并写入相应的设备节点中。而我们的Android 输入系统所做的事情概括起来说就是监控这些设备节点,当某个设备节点有数据可读时,将数据读出并进行一系列的翻译加工,然后在所有的窗口中找到合适的事件接收者,并派发给它。

在这里插入图片描述当点击事件产生后,事件会传递给当前的Activity,由Activity中的PhoneWindow完成,PhoneWindow再把事件处理工作交给DecorView,之后再有DecorView将事件处理工作交给ViewGroup
在这里插入图片描述
在这里插入图片描述

五、View的事件分发机制

事件分发到ViewGroupdispatchTouchEvent方法,如果它的onInterceptTouchEvent返回true,则由自己处理,这时如果它的mOnTouchListener被设置,则onTouch会被调用,否则onTouchEvent会被调用。在onTouchEvent中,如果设置了mOnCLickListener,则onClick会被调用。如果它的onInterceptTouchEvent返回false,则交给点击事件链上的子View处理,如此循环,完成分发。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如下是View完整的点击事件传递流程:
在这里插入图片描述
在这里插入图片描述

六、点击事件分发的传递规则

点击事件分发的3个重要方法的关系,伪代码表示:
在这里插入图片描述
【一些重要结论】

  1. 事件传递的优先级:onTouchListener.onTouch > onTouchEvent > onLongClickListener.onLongClick > onClickListener.onClick
  2. 正常情况下,一个时间序列只能被一个View拦截且消耗。因为一旦一个元素拦截了此事件,那么同一个事件序列内的所有事件都会直接交给它处理(即不会再调用这个View的拦截方法去询问它是否要拦截了,而是把剩余的ACTION_MOVE、ACTION_DOWN等事件直接交给它来处理)。特例:通过将重写View的onTouchEvent返回false可强行将事件转交给其他View处理。
  3. 如果View不消耗除ACTION_DOWN以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前View可以持续收到后续的事件,最终这些消失的点击事件会传递给Activity处理。
  4. ViewGroup默认不拦截任何事件(返回false)。
  5. View的onTouchEvent默认都会消耗事件(返回true),除非它是不可点击的(clickable和longClickable同时为false)。View的longClickable属性默认都为false,clickable属性要分情况,比如Button的clickable属性默认为true,而TextView的clickable默认为false。
  6. 通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN事件除外。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值