Android事件分发机制

90 阅读3分钟

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(),进行事件响应处理。

事件若在传递过程中被消费,整个分发流程则直接结束。