当一个View(纯View控件)接收到事件后,也会调用其dispatchTouchEvent(),然后在此方法内部会调用当前View的onTouchEvent(),如果onTouchEvent()返回true则表示要处理此事件。如果返回false表示不消耗事件,其上级View的onTouchEvent()将被调用,则事件流的后续部分不再传递到当前View,在一个事件流中也不会再调用当前View的dispatchTouchEvent()。
接下来通过具体示例来查看事件传递的流程:
示例一,默认情况下的事件传递流程创建3个类,一个Activity、一个继承自LinearLayout的View,一个继承自Button的View,并重写他们的dispatchTouchEvent()、onIntercepteTouchEvent()、onTouchEvent(),三个类及布局文件的代码如下:
EventDispatchActivity
/** * 事件分发机制测试Activity * Created by liuwei on 18/1/5. */ public class EventDispatchActivity extends AppCompatActivity { private final static String TAG = "Activity";//EventDispatchActivity.class.getSimpleName(); private EventDispatchTestView edtv_test; private EventDispatchLinearLayout edll_test; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_event_dispatch); edtv_test = ViewUtils.find(this, R.id.edtv_test); edll_test = ViewUtils.find(this, R.id.edll_test); } @Override public boolean dispatchTouchEvent(MotionEvent event) { // 被调用时输出log,event.getAction表示事件的类型,0:ACTION_DOWN,1:ACTION_UP,2:ACTION_MOVE。 Log.i(TAG, "dispatchTouchEvent: " + event.getAction() + " | 分发事件"); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i(TAG, "onTouchEvent: " + event.getAction() + " | 是否消耗事件:" + true); return super.onTouchEvent(event); } }EventDispatchLinearLayout
/** * 事件分发机制测试 ViewGroup * Created by liuwei on 18/1/5. */ public class EventDispatchLinearLayout extends LinearLayout { private final static String TAG = "——Layout";//EventDispatchLinearLayout.class.getSimpleName(); public EventDispatchLinearLayout(Context context) { super(context); } public EventDispatchLinearLayout(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i(TAG, "dispatchTouchEvent: " + event.getAction() + " | 分发事件"); return super.dispatchTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { Log.i(TAG, "onInterceptTouchEvent: " + event.getAction() + " | 是否拦截:" + false); return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i(TAG, "onTouchEvent: " + event.getAction() + " | 是否消耗事件:" + false); return super.onTouchEvent(event); } }EventDispatchTestView
/** * 事件分发机制测试 View * Created by liuwei on 18/1/5. */ public class EventDispatchTestView extends Button { private final static String TAG = "————View";//EventDistpatchTestView.class.getSimpleName(); public EventDispatchTestView(Context context) { super(context); } public EventDispatchTestView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i(TAG, "dispatchTouchEvent: " + event.getAction() + " | 分发事件"); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i(TAG, "onTouchEvent: " + event.getAction() + " | 是否消耗事件:" + true); return super.onTouchEvent(event); } }布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical" tools:context="cn.codingblock.view.event_dispatch.EventDispatchActivity"> <cn.codingblock.view.event_dispatch.EventDispatchLinearLayout android:id="@+id/edll_test" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#cccccc"> <cn.codingblock.view.event_dispatch.EventDispatchTestView android:id="@+id/edtv_test" android:layout_width="300dp" android:layout_height="300dp" android:layout_margin="10dp" android:background="#000000"/> </cn.codingblock.view.event_dispatch.EventDispatchLinearLayout> </LinearLayout>运行代码,点击EventDispatchTestView(黑色区域),log输出如下(log中的数字表示事件的类型,0:ACTION_DOWN,1:ACTION_UP,2:ACTION_MOVE):
01-05 16:58:05.574 23295-23295/cn.codingblock.view I/Activity: dispatchTouchEvent: 0 | 分发事件 01-05 16:58:05.574 23295-23295/cn.codingblock.view I/——Layout: dispatchTouchEvent: 0 | 分发事件 01-05 16:58:05.574 23295-23295/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 0 | 是否拦截:false 01-05 16:58:05.574 23295-23295/cn.codingblock.view I/————View: dispatchTouchEvent: 0 | 分发事件 01-05 16:58:05.574 23295-23295/cn.codingblock.view I/————View: onTouchEvent: 0 | 是否消耗事件:true 01-05 16:58:05.611 23295-23295/cn.codingblock.view I/Activity: dispatchTouchEvent: 2 | 分发事件 01-05 16:58:05.611 23295-23295/cn.codingblock.view I/——Layout: dispatchTouchEvent: 2 | 分发事件 01-05 16:58:05.611 23295-23295/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 2 | 是否拦截:false 01-05 16:58:05.611 23295-23295/cn.codingblock.view I/————View: dispatchTouchEvent: 2 | 分发事件 01-05 16:58:05.611 23295-23295/cn.codingblock.view I/————View: onTouchEvent: 2 | 是否消耗事件:true 01-05 16:58:05.619 23295-23295/cn.codingblock.view I/Activity: dispatchTouchEvent: 1 | 分发事件 01-05 16:58:05.619 23295-23295/cn.codingblock.view I/——Layout: dispatchTouchEvent: 1 | 分发事件 01-05 16:58:05.619 23295-23295/cn.codingblock.view I/——Layout: onInterceptTouchEvent: 1 | 是否拦截:false 01-05 16:58:05.620 23295-23295/cn.codingblock.view I/————View: dispatchTouchEvent: 1 | 分发事件 01-05 16:58:05.620 23295-23295/cn.codingblock.view I/————View: onTouchEvent: 1 | 是否消耗事件:true