事件分发
记住这张图就可以了,看不懂这张图的可以看下这篇文章
https://www.jianshu.com/p/e99b5e8bd67b

viewGroup的dispatchTouchEvent方法,先判断是否拦截,不拦截,根据MotionEvent事件的坐标x,y,遍历其所有的chidlView,判断childView是否包含此坐标x,y,如果坐标在childView中,分发事件给此childView;
在viewGroup的dispatchTouchEvent方法,会调用super.dispatchTouchEvent即View的dispatchTouchEvent;
在view的dispatchTouchEvent方法中,判断view是否有mOnTouchListener事件,并且enable为true,会有mOnTouchListener执行其onTouch方法;
如果mOnTouchListener的onTouch方法返回为true,view的dispatchTouchEvent方法返回就是true,即事件在dispatchTouchEvent方法中消费,其他事件也会传递到此方法消费,不会传递给onTouchEvent方法,不会触发onClick,onLongClick等事件;
onTouchEvent方法,对点击事件(MotionEvent.ACTION_UP)和长按点击事件(MotionEvent.ACTION_DOWN)有处理;
<?xml version="1.0" encoding="utf-8"?>
<viewtest.MyConstraitLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/root1">
<shijianfenfa.MyLinearLayout
android:id="@+id/root_linear"
android:layout_width="match_parent"
android:layout_height="match_parent">
<viewtest.MyTextView
android:id="@+id/mytextview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</shijianfenfa.MyLinearLayout>
<shijianfenfa.MyRelativeLayout
android:id="@+id/myrelative"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</viewtest.MyConstraitLayout>
情景一:每个view都是全屏的,如果都没有设置点击事件,每个控件都设置了mOnTouchListener事件,onTouch方法返回的为false,这四个控件的onTouch方法都会触发;都只会出发一次onTouch事件,传入的是MotionEvent.ACTION_DOWN;对MotionEvent.ACTION_DOWN事件没有消费,后续的其他事件不会再传入;
情景二:MyLinearLayout设置点击事件,并设置mOnTouchListener,onTouch方法返回为true,触摸事件被MyLinearLayout的dispatchTouchEvent消费,不会走onTouchEvent方法,不会触发点击事件,但是会把后续的MotionEvent事件都传入到dispatchTouchEvent方法消费,同时mOnTouchListener的onTouch方法也会走,可以在onTouch方法中处理点击事件(MotionEvent.ACTION_UP);
总结:
1.事件的传递是从MotionEvent.ACTION_DOWN开始传递,如果MotionEvent.ACTION_DOWN事件没有处理,后面的MotionEvent.ACTION_UP,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_CANCEL等事件都不会往下传递,都不会处理
2.事件的开始必须是MotionEvent.ACTION_DOWN,如果接收到的第一个事件是MotionEvent.ACTION_UP等(除了MotionEvent.ACTION_DOWN之外的),都不会处理;
比如:两个button,B1,B2,都设置了点击事件,在同一个界面,按下B1,没有松开,滑动到B2,这两个button都不会响应点击事件;
3.onTouchEvent方法,对点击事件是在MotionEvent.ACTION_UP中处理,长按点击事件是在MotionEvent.ACTION_DOWN中处理;
4.如果mOnTouchListener的onTouch方法返回为true,view的dispatchTouchEvent方法返回就是true,即事件在dispatchTouchEvent方法中消费,其他事件也会传递到此方法消费,不会传递给onTouchEvent方法,不会触发onClick,onLongClick等事件;事件交给mOnTouchListener的onTouch方法处理;