前言
每次听说事件分发就觉得好难、肯定不好学,其实事件分发也就那么回事。将本文看下去不说你能对事件分发有多么了解、多么深入,但是在应用开发中简单的使用是绝对没有问题的,下面咱就不叨叨,开始咱们的学习。
Android Touch事件的分发是 Android 工程师必备技能之一。关于事件分发主要有几个方向可以展开深入分析:
- 1.Touch事件是如何从驱动层传递给 Framework 层的 InputManagerService;
- 2.WMS是如何通过 ViewRootImpl 将事件传递到目标窗口;
- 3.Touch事件到达 DecorView 后,是如何一步步传递到内部的子 View 中的。
名词了解
- AMS:统一调度所有应用程序的Activity
- WMS:控制所有Window的显示与隐藏以及要显示的位置
什么是事件
事件:Touch,既触碰,就是用户触碰手机界面的交互事件。事件主要包括:按下、滑动、抬起与取消。这些事件被封装成MotionEvent对象。该对象中的主要事件如下表所示:
事件流
按下、滑动、抬起、取消这几种事件组成了一个事件流。事件流以按下为开始,中间可能有若干次滑动,以抬起或取消作为结束。
什么是事件分发
事件分发:就是将一次完整的点击所包含的点击事件传递到某个具体的View或ViewGroup,让该View或该ViewGroup处理(消费)它。分发是「从上往下依次传递」的,其中可能经过的对象有「最上层Activity」,「中间层ViewGroup」,「最下层View」。例如在屏幕中有一个Button控件,点击它时该次点击事件就会从Activity传到Button所在的ViewGroup,最后传到该Button控件去处理它。即事件分发就是从上往下依次遍历,直到找到能够处理消费这次点击事件的View或ViewGroup。
在Android对事件分发的处理过程中,主要是对「Down事件作分发」,进而找到能够处理Down事件的组件。对于事件流中后续的事件(如Move、Up等),则直接分发给能够处理按下事件的组件。故本文讨论的内容则是主要针对按下事件的。
思路梳理
在深入分析事件分发源码之前,需要先弄清楚2个概念。
ViewGroup
ViewGroup 是一组 View 的组合,在其内部有可能包含多个子 View,当手指触摸屏幕上时,手指所在的区域既能在ViewGroup显示范围内,也可能在其内部 View 控件上。因此它内部的事件分发的重心是处理当前 ViewGroup 和子 View 之间的逻辑关系:
- 1.当前 ViewGroup 是否需要拦截Touch事件;
- 2.是否需要将Touch事件继续分发给子 View;
- 3.如何将Touch事件分发给子 View。
View
View 是一个单纯的控件,不能再被细分,内部也并不会存在子 View,所以它的事件分发的重点在于当前 View 如何去处理 Touch 事件,并根据相应的手势逻辑进行一些列的效果展示(比如滑动,放大,点击,长按等)。
- 1.是否存在 TouchListener;
- 2.是否自己接收处理 touch 事件(主要逻辑在 onTouchEvent 方法中)。
涉及事件分发的方法
方法的简单用途解析
我们可以发现这三个方法的返回值都为boolean类型,其实它们就是通过返回值来决定下一步的传递处理方向。
1、dispatchTouchEvent() ——用来分发事件所用
该方法会将Touch事件「自上而下」依次分发到子元素中,直到被终止或者到达View层,该方法也是采用一种「隧道方式来分发」。在其中会调用onInterceptTouchEvent()和onTouchEvent(),「一般不会重写」。
- 返回false则不拦截继续往下分发;
- 返回true则拦截住该事件不在向下层元素分发;
在dispatchTouchEvent()方法中默认返回false。
2、onInterceptTouchEvent() ——用来拦截事件所用
- 返回false不拦截事件,Touch事件就会往下传递给其子View。
- 返回true,该事件将会被拦截,并且被当前ViewGroup处理,调用ViewGroup的onTouchEvent()方法。
3、onTouchEvent() ——用来处理事件
- 返回true则表示该View能处理该事件,事件将终止向上传递(传递给其父View)。
- 返回false表示不能处理,则把事件传递给其父View的onTouchEvent()方法来处理。
拥有上述方法的类
「注意:」 需要特别注意一点就是ViewGroup中额外拥有onInterceptTouchEvent()方法,其他两个方法为这三种类所共同拥有。
事件分发流程
单个事件触发后,事件分发流程:Activity①>ViewGroup②>View③,如下图:
即要想充分理解Android分发机制,本质上是要理解:
- Activity对点击事件的分发机制
- ViewGroup对点击事件的分发机制
- View对点击事件的分发机制
从U型图中可以发现,由父组件不断向子组件分发,若子组件能够处理,则立刻返回。若子组件都不处理,那传递到底层的子组件,再返回回来。「整个View之间的事件分发,实质上就是一个大的递归函数」。