最详细的 Android View 的事件分发原理_android view事件分发

Android 的 View 的事件分发一直是老生常谈的问题,市面上的所有文章资料都在通过 dispatchTouchEvent、onInterceptTouchEvent 和 onTouchEvent 讲事件分发的原理,对于一些细节没有涉及,本文带你一窥源码,搞清楚 View 是如何选择事件处理的。

MotionEvent

MotionEvent 定义了用于报告移动(鼠标、笔、手指、轨迹球)事件的对象。运动事件可以保存绝对或相对运动和其他数据,这取决于设备的类型。

用户触摸一次屏幕将会产生 MotionEvent 事件,并将事件传递给合适的 View 。MotionEvent 会包含一些触摸行为的相关信息,例如事件的类型、触摸的X和Y坐标、接触区域的大小和方向的信息等等。有些设备可以同时报告多条移动轨迹。多点触控屏幕为每个手指发出一个运动轨迹。单个的手指或其他产生运动轨迹的对象称为指针。

通常情况下,用户的触摸事件类型包括:按下(ACTION_DOWN)、移动(ACTION_MOVE)、抬起(ACTION_UP)、取消(ACTION_CANCEL)。

用户的一次触摸通常以 ACTION_DOWN 事件开始,在屏幕上移动时产生多个 ACTION_MOVE 事件,最后抬起手指触发 ACTION_UP 或 ACTION_CANCEL 事件。

View 和 ViewGroup

在讲解事件分发机制之前,要区分 View 和 ViewGroup ,尽管 ViewGroup 继承自 View ,但是它们代表了不容的概念。 Android 的视图结构是树结构,View 代表的是叶子节点,而 ViewGroup 则表示可以拥有子节点的非叶子节点。它们的事件分发逻辑是有区别的。

简述事件分发

下文的分析可能比较复杂,这里总结一下事件分发涉及核心方法的流程:

View 的事件分发流程

当触摸事件来临时,会触发 View 的 dispatchTouchEvent(event) 将事件进行分发。如果 View 设置了 onTouchListener ,会优先回调 onTouch(view, event) ,onTouch 方法的返回值表示是否处理事件。

如果 onTouch 不处理事件,会进入 View 自己的 onTouchEvent ,在没有覆盖的情况下,该方法内部会识别该事件是点击、长按或其他类型,点击会调用 performClick() ,perfromClick 方法会调用 onClickListener 的 onClick(View)

onTouchEvent 方法用户可以自己来实现,从而实现 View 的拖拽等能力。

如果 onTouchEvent 方法也返回 false ,说明当前 View 不消耗这个事件,dispatchTouchEvent 返回 false 。

ViewGroup 的事件分发流程

当触摸事件来临时,会触发 ViewGroup 的 dispatchTouchEvent 将事件进行分发。

ViewGroup 会优先处理事件的分发逻辑,经过窗口的检查后,首先会通过通过 Flag 检查是否需要拦截,并调用 onInterceptTouchEvent(event) 确定真正是否进行拦截的结果。然后进行取消的 Flag 检查。

在不拦截不取消的情况下,通过 View 的渲染顺序和 Z 轴顺序会生成一个有序的 View 列表,根据列表顺序获取符合事件坐标位置的 View ,然后通过 dispatchTransformedTouchEvent(view, ...) 来分发给这个 View ,dispatchTransformedTouchEvent 方法内部调用 view.dispatchTouchEvent(event) ,如果 view 为空的情况,直接调用 super.dispatchTouchEvent(event) ,也就是调用 ViewGroup 的父类 View 的 dispatchTouchEvent 方法。

如果子 View 不消耗事件(dispatchTouchEvent 方法返回了 false),ViewGroup 会调用 dispatchTransformedTouchEvent(view = null, ...) 的形式,调用到自己的 super.dispatchTouchEvent(event) ,也就是将自己视为最后 View 来检查是否消耗。

View dispatchTouchEvent

View 的 dispatchTouchEvent 方法会将触摸屏运动事件传递到目标视图,如果是目标,则传递给这个视图。并返回当前 View

  • 26
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值