事件传递

206 阅读4分钟

android事件传递顺序:Activity -> ViewGroup -> View。
各自事件:

  • Activity

    1. dispatchTouchEvent
    2. onTouchEvent
  • ViewGroup

    1. dispatchTouchEvent
    2. onInterceptTouchEvent
    3. onTouchEvent
  • View

    1. dispatchTouchEvent
    2. onTouchEvent

demo

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.example.lexchat.view.ViewGroupA
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#fa0"
        android:orientation="vertical"
        android:padding="20dp">

        <com.example.lexchat.view.ViewA
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:background="#ff0000"
            android:text="ViewA"/>

        <com.example.lexchat.view.ViewGroupB
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="#00ff00"
            android:layout_marginTop="10dp"
            android:gravity="center">

            <com.example.lexchat.view.ViewB
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:background="#0000ff" />
        </com.example.lexchat.view.ViewGroupB>
    </com.example.lexchat.view.ViewGroupA>
</LinearLayout>

ui

默认流程

点击ViewA事件:

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewA  dispatchTouchEvent -----> ACTION_DOWN
ViewA  onTouchEvent -----> ACTION_DOWN
ViewGroupA  onTouchEvent -----> ACTION_DOWN
TouchActivity  onTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
TouchActivity  onTouchEvent -----> ACTION_UP

点击ViewGroupA事件:

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupA  onTouchEvent -----> ACTION_DOWN
TouchActivity  onTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
TouchActivity  onTouchEvent -----> ACTION_UP

通过ViewA和ViewGroupA的事件可以看到事件如果在传递过程中没有被消费的话(return true),是从Activity的dispatchTouchEvent开始的,然后按层级依次向下传递,直到最后一个View或者ViewGroup,调用它的onTouchEvent;然后依次向上传递,直到Activity的onTouchEvent。看着是一个U型结构:

default

事件消费

dispatchTouchEvent

Activity

测试代码:

public boolean dispatchTouchEvent(MotionEvent ev) {
        MotionEventUtil.log(TAG, "dispatchTouchEvent", ev.getAction());
        boolean result = super.dispatchTouchEvent(ev);
        MotionEventUtil.log(TAG, "super.dispatchTouchEvent", ev.getAction(), result);
        return result;
    }

boolean result = true 执行结果:

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN

TouchActivity  dispatchTouchEvent -----> ACTION_UP

boolean result = false 结果:

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN


TouchActivity  dispatchTouchEvent -----> ACTION_UP

观察上面dispatchTouchEvent不管返回true或者false,本次事件(ACTION_DOWN)立即结束,不再向下传递。

ViewGroup

ViewGroupA的dispatchTouchEvent 返回true,点击ViewA:

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN

TouchActivity  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  dispatchTouchEvent -----> ACTION_UP

ViewGroupA执行完dispatchTouchEvent事件直接结束。

ViewGroupB的dispatchTouchEvent 返回true,点击ViewB

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupB  dispatchTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  onInterceptTouchEvent -----> ACTION_UP
ViewGroupB  dispatchTouchEvent -----> ACTION_UP

ViewGroupB执行完dispatchTouchEvent直接结束。

View

ViewB的dispatchTouchEvent 返回true,点击ViewB

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupB  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupB  onInterceptTouchEvent -----> ACTION_DOWN
ViewB  dispatchTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  onInterceptTouchEvent -----> ACTION_UP
ViewGroupB  dispatchTouchEvent -----> ACTION_UP
ViewGroupB  onInterceptTouchEvent -----> ACTION_UP
ViewB  dispatchTouchEvent -----> ACTION_UP

执行到ViewB的dispatchTouchEvent就结束了。

综上当dispatchTouchEvent返回true的时候(返回true就表明本次事件已经消耗掉),不会向下传递也不会向上传递,本次事件就直接结束。


ViewGroupB的dispatchTouchEvent 返回false,点击ViewB

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupB  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onTouchEvent -----> ACTION_DOWN
TouchActivity  onTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
TouchActivity  onTouchEvent -----> ACTION_UP

ViewB的dispatchTouchEvent 返回false,点击ViewB:

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupB  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupB  onInterceptTouchEvent -----> ACTION_DOWN
ViewB  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupB  onTouchEvent -----> ACTION_DOWN
ViewGroupA  onTouchEvent -----> ACTION_DOWN
TouchActivity  onTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
TouchActivity  onTouchEvent -----> ACTION_UP

不管是ViewGroup还是View,如果dispatchTouchEvent返回false,就表明不再向下分发事件,直接交由上一级View的onTouchEvent继续向上传递。

总结:

  • 返回super.dispatchTouchEvent
    事件继续按U型结构执行,直到被消耗。
  • 返回true
    表明事件直接就被消耗了,事件不会向下分发也不会向上传递,本次事件就直接结束。
  • 返回false
    表明不再向下分发事件,直接交由上一级View的onTouchEvent继续向上传递。要注意下次事件的传递.

onInterceptTouchEvent

ViewGroupB的onInterceptTouchEvent 返回true,点击ViewB

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupB  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupB  onInterceptTouchEvent -----> ACTION_DOWN

ViewGroupB  onTouchEvent -----> ACTION_DOWN
ViewGroupA  onTouchEvent -----> ACTION_DOWN
TouchActivity  onTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
TouchActivity  onTouchEvent -----> ACTION_UP

ViewGroupB的onInterceptTouchEvent 返回false,点击ViewB

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupB  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupB  onInterceptTouchEvent -----> ACTION_DOWN

ViewB  dispatchTouchEvent -----> ACTION_DOWN
ViewB  onTouchEvent -----> ACTION_DOWN
ViewGroupB  onTouchEvent -----> ACTION_DOWN
ViewGroupA  onTouchEvent -----> ACTION_DOWN
TouchActivity  onTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
TouchActivity  onTouchEvent -----> ACTION_UP

和super.onInterceptTouchEvent一样。
总结:

  • 返回true 进行事件拦截,停止向下分发,交给自己的onTouchEvent,然后向上传递。
  • 返回false和super.onInterceptTouchEvent 不进行拦截,事件向下传递给下级dispatchTouchEvent,按U型结构继续分发。

onTouchEvent

ViewGroupB的onTouchEvent 返回true,点击ViewB

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupB  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupB  onInterceptTouchEvent -----> ACTION_DOWN
ViewB  dispatchTouchEvent -----> ACTION_DOWN
ViewB  onTouchEvent -----> ACTION_DOWN
ViewGroupB  onTouchEvent -----> ACTION_DOWN

TouchActivity  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  onInterceptTouchEvent -----> ACTION_UP
ViewGroupB  dispatchTouchEvent -----> ACTION_UP
ViewGroupB  onTouchEvent -----> ACTION_UP

ViewGroupB的onTouchEvent返回true,事件被消费,事件终止。

ViewB的onTouchEvent返回true,点击ViewB

TouchActivity  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupA  onInterceptTouchEvent -----> ACTION_DOWN
ViewGroupB  dispatchTouchEvent -----> ACTION_DOWN
ViewGroupB  onInterceptTouchEvent -----> ACTION_DOWN
ViewB  dispatchTouchEvent -----> ACTION_DOWN
ViewB  onTouchEvent -----> ACTION_DOWN
TouchActivity  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  dispatchTouchEvent -----> ACTION_UP
ViewGroupA  onInterceptTouchEvent -----> ACTION_UP
ViewGroupB  dispatchTouchEvent -----> ACTION_UP
ViewGroupB  onInterceptTouchEvent -----> ACTION_UP
ViewB  dispatchTouchEvent -----> ACTION_UP
ViewB  onTouchEvent -----> ACTION_UP

ViewB消耗事件,事件结束。

总结:

  • 返回true 事件被消费,直接结束
  • 返回false或者super.onTouchEvent 事件不处理,继续向上传递。
  • 下次事件不会走当前消费事件ViewGroup的onInterceptTouchEvent方法。

dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent三个方法如果调用super.XXX,默认都返回false。但是当给View或者ViewGroup支持点击或者长按的话,事件就会被该View或者ViewGroup消费,返回true。比如设置clicklistener或者设置setClickable(true)