总的来说,事件分发的传递方向是由外向内的。当触碰事件(MotionEvent)产生,最先接受到的是Activity,然后传递给Window,再由Window传递给布局中的视图层级。由最外层的ViewGroup根据触发区域向下分发到具体的View。
事件分发涉及到的比较关键的方法是dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent。
View和ViewGroup中的事件分发都是从dispatchTouchEvent开始,onInterceptTouchEvent方法是VIewGroup才有,View类中没有的。
onInterceptTouchEvent方法表示是否拦截事件。如果返回true,则表示当前ViewGroup拦截事件,事件不会传递给子元素child。此时ViewGroup的onTouchEvent方法会被执行,即消耗当前事件。并且同一事件序列内的其他事件也由它的onTouchEvent处理,不需要通过onInterceptTouchEvent再去询问是否拦截。
如果ViewGroup没有拦截事件,事件会传递到子元素View的dispatchTouchEvent方法。在View的dispatchTouchEvent方法中,会先判断OnTouchListener.onTouch的返回值。
如果OnTouchListener为null或者onTouch方法返回false,则会将事件传到onTouchEvent方法
如果onTouch放回true,则dispatchTouchEvent方法会直接返回true,onTouchEvent不会执行,事件被onTouch消耗。
事件传递到onTouchEvent,如果返回false,事件会回传给它的父元素来处理,且同一个事件序列中的其他事件不会在由它处理。某个View一旦开始处理事件,如果它不消耗ACTION_DOWN事件(onTouchEvent返回了false),那么同一个事件序列中的其他事件都不会交给它来处理,并且事件序列会回传给它的父元素去处理,父元素的onTouchEvent会被调用。
如果View的onTouchEvent返回true,则表示事件由当前View消耗,且同一事件序列的其他事件也由它来处理。
默认情况下,只有当控件是不可点击的,即CLICKABLE和LONG_CLICKABLE都是false,onTouchEvent方法才会返回false。onCLick会触发的前提是View是可点击的,并且它收到了ACTION_DOWN和ACTION_UP。
通常一个事件序列的所有事件都是由通过一个View来消耗处理。子元素可以通过requestDisallowInterceptTouchEvent方法干预父元素的事件分发过程,但是ACTION_DOWN事件除外。