Android 事件传递机制

事件传递机制

事件传递机制,简洁概括如下,建议代码里面打log看调用顺序。

1. dispatchTouchEvent
事件分发函数,return false事件向下分发,return true,事件不向下,也不向上分发了,到该层控件的onTouchEvent(反复执行)
重写该函数的话需要调用super,否则事件不会分发出去

2. onInterceptTouchEvent
负责事件是否向下传递,事件拦截函数,return false 不拦截事件,事件继续向下传递,return true拦截事件,事件不向下传递,从该层控件开始向上传递,直到Activity的onTouchEvent(反复执行)
那这个函数一般什么时候用呢?一般是在一个可以滑动的列表里,有时事件需要让子控件处理时(requestDisallowInterceptTouchEvent),就要用到

3. onTouchEvent
负责事件是否向上传递,return false事件继续向下传递,最终到Activity的onTouchEvent,return true消费事件,事件不继续向上传递及向下传递,反复循环执行该控件的onTouchEvent

如下,在布局里第一层放了一个LinearLayout,第二层也放了一个LinearLayout,第三层放了个TextView

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.testeventpass.MainActivity">

    <com.example.testeventpass.MyLinearLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:layout_margin="20dp"
        >

        <com.example.testeventpass.MyLinearLayoutOther
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="#999999"
            android:gravity="center"
            android:layout_margin="20dp"
            >

            <com.example.testeventpass.MyTextView
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:layout_gravity="center"
                android:background="@color/colorAccent"
                android:gravity="center"
                />
        </com.example.testeventpass.MyLinearLayoutOther>

    </com.example.testeventpass.MyLinearLayout>
</FrameLayout>

a.默认返回值方式

b.dispatchTouchEvent 返回true

c.onInterceptTouchEvent 返回true

d.onTouchEvent 返回true

    @Override
   public boolean onInterceptTouchEvent(MotionEvent ev) {
       Log.e("mytestt","..........MyLinearLayout onInterceptTouchEvent run");

       switch (ev.getAction())
       {
           case MotionEvent.ACTION_DOWN:
               Log.e("mytestt","MotionEvent.ACTION_DOWN");
              return true;
           case MotionEvent.ACTION_MOVE:
               Log.e("mytestt","MotionEvent.ACTION_MOVE");
               return false;
           case MotionEvent.ACTION_UP:
               Log.e("mytestt","MotionEvent.ACTION_UP");
               return false;
       }

       boolean value =  super.onInterceptTouchEvent(ev);
       Log.e("mytest","MyLinearLayout onInterceptTouchEvent:"+value);
       return true;
   }

   @Override
   public boolean onTouchEvent(MotionEvent event) {
       Log.e("mytestt","..........MyLinearLayout onTouchEvent run");

       switch (event.getAction())
       {
           case MotionEvent.ACTION_DOWN:
               Log.e("mytestt","onTouchEvent MotionEvent.ACTION_DOWN");
               return true;
           case MotionEvent.ACTION_MOVE:
               Log.e("mytestt","onTouchEvent MotionEvent.ACTION_MOVE");
               return false;
           case MotionEvent.ACTION_UP:
               Log.e("mytestt","onTouchEvent MotionEvent.ACTION_UP");
               return false;
       }

       boolean value =  super.onTouchEvent(event);
       Log.e("mytest","MyLinearLayout onTouchEvent:"+value);
       return value;
   }

在上述代码在MyLinearLayout中,onInterceptTouchEvent在ACTION_DOWN时return true,则事件向下传不到MyLinearLayoutOther,若在ACTION_MOVE或者ACTION_UP中return true,则不起作用,事件依然向下传递。
onTouchEvent在ACTION_DOWN时return true,则事件向上传不到MainActivity,若在ACTION_MOVE或者ACTION_UP中return true,则不起作用,事件依然向上传递。

源码参考samples里面的TestEventPass

源码下载

Leach Chen

Leach Chen

I am an Android developer.I will add description latter.