1、前言
用户在使用app时,会经常频繁触摸屏幕,点击页面交互。用户触摸点击的动作,就涉及到app中相关UI的触摸和点击事件。事件在UI中传递和处理的过程,就是事件分发流程。
2、事件分发流程概述
事件分发过程中,涉及到3种UI对象类型:Activity、ViewGroup、View及其派生类。3者间的关系:

发生1次点击事件时,事件会按照Activity->ViewGroup->View的顺序,进行事件传递。
- Activity:控制UI页面的生命周期,是事件分发的入口。
- ViewGroup:View的特殊子类,是1组View的集合,是Android中所有布局的父类。
- View:所有UI组件的基类,常见的Button、TextView等控件都继承自View。
Android事件分发机制,其实就是Activity、ViewGroup、View3者对触摸点击事件的事件传递过程。
3、事件分发流程详细分析
在整个事件分发,并响应事件的过程中,有3个重要的方法:
- dispatchTouchEvent:分发(传递)点击事件,当点击事件能传递给当前View时,该方法就会被调用。
- onInterceptTouchEvent:判断是否拦截某个事件,该方法仅在ViewGroup中存在。1般情况下会在ViewGroup的dispatchTouchEvent方法中调用该方法。
- onTouchEvent:处理点击事件,在dispatchTouchEvent内部调用。
下面依次对Activity、ViewGroup、View3种UI对象类型,结合上述3个事件方法,做1下具体分析。
3.1 Activity的事件分发流程
Activity 中包含2个事件分发与处理的方法:
- boolean dispatchTouchEvent(MotionEvent ev):事件分发
- boolean onTouchEvent(MotionEvent event):事件消费
当1个事件发生时,首先会将点击事件传递到Activity中,执行 dispatchTouchEvent 进行事件分发。经过window、decorView依次传递后,页面上的 ViewGroup会接收到该事件。ViewGroup若消费了该事件,则分发结束,未消费则继续调用Activity的 onTouchEvent 方法处理事件,简略流程图如下:

3.2 ViewGroup的事件分发流程
ViewGroup 中包含3个事件分发与处理的方法:
- dispatchTouchEvent(MotionEvent ev):事件分发
- onIntercepTouchEvent(MotionEvent ev):事件拦截
- onTouchEvent(MotionEvent ev):事件消费
ViewGroup的事件分发机制从dispatchTouchEvent开始,接着调用onInterceptTouchEvent判断是否需拦截事件。
若需拦截,则表示当前 ViewGroup 希望处理该事件,或不希望子 View 处理该事件,此时将直接调用 onTouchEvent处理事件。onTouchEvent 方法若消费了该事件,则分发结束,未消费则调用Activity的 onTouchEvent 方法处理事件。
若不需拦截,则会遍历寻找被点击的子View,将该事件传递给子 View 的 dispatchTouchEvent。若未找到子View,事件将会继续传递给ViewGroup的 onTouchEvent 方法,与事件被拦截的效果1致。
主要的事件分发链路图如下所示:

3.3 View的事件分发流程
View 中包含如下2个事件分发与处理的方法:
- dispatchTouchEvent(MotionEvent event)
- onTouchEvent(MotionEvent event)
View通过 dispatchTouchEvent接收到从ViewGroup传递过来的事件后,直接调用 onTouchEvent处理事件。若消费了该事件,则分发结束,未消费则调用ViewGroup的 onTouchEvent方法处理事件。所以 View 中的事件处理流程很简单,如下图:

此处说明1个细节,当View把事件消费后,若View的 onTouch 方法返回true,View的 dispatchTouchEvent 方法会直接返回true,不会再调用View的 onClick 方法。只有当 onTouch 方法返回false时,才会有 onClick 事件处理。
四、总结
Android事件分发流程:Activity -> ViewGroup -> View。即:1个点击事件发生后,事件先传到Activity、再传到ViewGroup、最终再传到View。从上往下依次调用dispatchTouchEvent(),进行事件分发。
Android事件消费流程:View -> ViewGroup -> Activity。从下往上依次调用onTouchEvent(),进行事件响应处理。
事件若在传递过程中被消费,整个分发流程则直接结束。