什么是事件?事件是用户触摸手机屏幕,引起的一系列TouchEvent,包括ACTION_DOWN、ACTION_MOVE、ACTION_UP、ACTION_CANCEL等,这些action组合后变成点击事件、长按事件等。
在这篇文章中,用打Log测试的方法来了解Android TouchEvent 事件分发,拦截,处理过程。虽然看了一些其他的文章和源码及相关的资料,但是还是觉得需要打下Log和画图来了解一下,不然很容易忘记了事件传递的整个过程。所以写下这篇文章,达到看完这篇文章基本可以了解整个过程,并且可以自己画图画出来给别人看。
先看几个类,主要是画出一个3个ViewGroup叠加的界面,并在事件分发、拦截、处理时打下Log.
GitHub地址:https://github.com/libill/TouchEventDemo
一、通过打log分析事件分发这里在一个Activity上添加三个ViewGroup来分析,这里值得注意的是Activity、View是没有onInterceptTouchEvent方法的。
一、了解Activity、ViewGroup1、ViewGroup2、ViewGroup3四个类
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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.touchevent.demo.MyActivity"> <com.touchevent.demo.ViewGroup1 android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent"> <com.touchevent.demo.ViewGroup2 android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="50dp" android:background="@color/colorPrimary"> <com.touchevent.demo.ViewGroup3 android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="50dp" android:background="@color/colorPrimaryDark"> </com.touchevent.demo.ViewGroup3> </com.touchevent.demo.ViewGroup2> </com.touchevent.demo.ViewGroup1> </android.support.constraint.ConstraintLayout>
主界面:MainActivity.java
public class MyActivity extends AppCompatActivity { private final static String TAG = MyActivity.class.getName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev)); boolean superReturn = super.dispatchTouchEvent(ev); Log.d(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + superReturn); return superReturn; } @Override public boolean onTouchEvent(MotionEvent ev) { Log.i(TAG, "onTouchEvent action:" + StringUtils.getMotionEventName(ev)); boolean superReturn = super.onTouchEvent(ev); Log.d(TAG, "onTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + superReturn); return superReturn; } }
三个ViewGroup,里面的代码完全一样:ViewGroup1.java,ViewGroup2.java,ViewGroup3.java。由于代码一样所以只贴其中一个类。
public class ViewGroup1 extends LinearLayout { private final static String TAG = ViewGroup1.class.getName(); public ViewGroup1(Context context) { super(context); } public ViewGroup1(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev)); boolean superReturn = super.dispatchTouchEvent(ev); Log.d(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + superReturn); return superReturn; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i(TAG, "onInterceptTouchEvent action:" + StringUtils.getMotionEventName(ev)); boolean superReturn = super.onInterceptTouchEvent(ev); Log.d(TAG, "onInterceptTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + superReturn); return superReturn; } @Override public boolean onTouchEvent(MotionEvent ev) { Log.i(TAG, "onTouchEvent action:" + StringUtils.getMotionEventName(ev)); boolean superReturn = super.onTouchEvent(ev); Log.d(TAG, "onTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + superReturn); return superReturn; } } 二、不拦截处理任何事件添加没有拦截处理任何事件的代码,看看事件是怎么传递的,选择Info,查看Log.
从流程图可以看出,事件分发从Activity开始,然后分发到ViewGroup,在这个过程中,只要ViewGroup没有拦截处理,最后还是会回到Activity的onTouchEvent方法。
三、ViewGroup2的dispatchTouchEvent返回true