32、Android事件分发机制

事件分发机制

Android 中与 Touch 事件相关的方法包括:

dispatchTouchEvent(MotionEvent ev)

onInterceptTouchEvent(MotionEvent ev)

onTouchEvent(MotionEvent ev);

能够响应这些方法的控件包括:Activity、ViewGroup和View,方法与控件的对应关系如下表所示:

Touch事件相关方法 方法功能 Activity ViewGroup View
dispatchTouchEvent(MotionEvent ev) 事件分发 Yes Yes Yes
onInterceptTouchEvent(MotionEvent ev) 事件拦截 No Yes No
onTouchEvent(MotionEvent ev) 事件响应 Yes Yes Yes

从表中可以看出,Activity和View都没有onInterceptTouchEvent(MotionEvent ev)方法,所以它们不能对事件进行拦截操作,可以拦截的只有ViewGroup。

三个方法的执行顺序如下:

dispatchTouchEvent(MotionEvent ev) -> onInterceptTouchEvent(MotionEvent ev) -> onTouchEvent(MotionEvent ev)

事件分发的过程具体如下图所示:

每个方法都有三种返回状态:Super、True、False。三种返回状态的描述如下:

  • Super:调用父类方法
  • True:消费事件,即事件不继续往下传递
  • False:不消费事件,事件也不继续往下传递 或者交由给父控件onTouchEvent()处理

接下来我们分析Activity、ViewGroup和View中的事件分发。

事件流程分析

  • Activity

Android系统默认不会拦截所有的事件,当事件传递到Activity时,dispatchTouchEvent会先接收到事件,这里有两种情况:

Super:默认不拦截事件,传递给子ViewGroup或View的dispatchTouchEvent()方法。

True或False:消费掉事件,不再向下传递。(猜测事件传递给DecView消费)

所以,在开发过程中,尽量不要在Activity中的dispatchTouchEvent()方法中返回True或False,会导致所有控件都无法接收事件。

  • ViewGroup

当ViewGroup的dispatchTouchEvent()方法接收到事件时,有三种情况需要考虑:

Super:分发事件,将事件传递给当前的onInterceptTouchEvent()方法。

True:不分发事件,将事件传递给父容器的dispatchTouchEvent()方法去处理。

False:不分发事件,将事件传递给父容器的OnTouchEvent()消费掉。

当dispatchTouchEvent()为Super的情况下,ViewGroup的onInterceptTouchEvent()方法会响应,这里有两种情况:

Super或False:不拦截事件,将事件传递给子ViewGroup或View的dispatchTouchEvent()方法。

True:拦截事件,当前的OnTouchEvent()方法会响应。

OnTouchEvent也有两种情况:

Super或False:将事件传递到父容器的OnTouchEvent去处理。

True:直接消耗掉事件。

  • View

当View的dispatchTouchEvent()方法接收到事件时,有三种情况:

Super:分法事件,将事件传递给当前的OnTouchEvent去处理。

True:不分发事件,将事件传递给父容器的dispatchTouchEvent()方法去处理。

False:将事件传递到父容器的OnTouchEvent()去处理。

当View的OnTouchEvent()方法接收到事件时,有两种情况:

Super或False:传递事件到父容器的OnTouchEvent()去处理。

True:在当前OnTouchEvent()方法中消耗事件。

注意:在dispatchTouchEvent()中,返回True和False后,后续的Move和Up事件会继续分发到该View或ViewGroup。

总结:Android事件的机制非常的复杂,图中还是存在一些错误以及一些没有讲到的地方,需要自己动手去验证才最实际。

原文地址:https://www.cnblogs.com/pengjingya/p/14952702.html