Touch事件MotionEvent拦截发生在ViewGroup的onInterceptTouchEvent和onTouchEvent方法以及View的onTouchEvent方法中。当发生touch事件时,系统会产生一个MotionEvent并且沿着View Tree开始传递。首先获取MotionEvent是View Tree的根节点,根节点通常是一个ViewGroup,ViewGroup将在方法onInterceptTouchEvent()中获取MotionEvent并决定是否继续向下传递。当在ViewGroup's onInterceptEvent()中返回true时,将截MotionEvent,View Tree下面的View将无法获得MotionEvent,转而交给当前ViewGroup'sonTouchEvent()方法。如果onTouchEvent中返回false,那么MotionEvent将沿着View Tree向上传给上一层。拦截的过程草图如下:
明白了touch事件的拦截机制之后,View tree中的各个层之间的分工也就更加明确了。
如果viewGroup对象的onIterceptEvent()方法返回ture,则MotionEvent不会传递到子view,直接执行viewGroup对象的onTouchEvent()。如果viewGroup.onTouchEvent()执行完返回true,则MotionEvent不会向上传递。如果onTouchEvent中返回false,那么MotionEvent将沿着View Tree向上传给上一层。如果viewGroup对象的onInterceptEvent()方法返回false,那么MotionEvent会沿着View Tree下面的View继续传递。
简单地概括:onInterceptEvent和onTouchEvent都是返回ture的时候不继续传递(本身感兴
趣消费事件,不用继续传递),返回false的时候继续传递。
注意:如果我们实现了View.onTouchListern接口,并通过View对象的setOnTouchListern注册了View的回调方法,那么MotionEvent会先传递给View.OnTouchLister的回调方法OnTouch,如果OnTouch方法return false则MotionEvent会继续传递给View.OnTouchEnent()方法。如果onTouch方法return ture,则View的onTouchEvent方法不会调用。
View的dispatchTouchEvent(MotionEvent event)方法负责分发MotionEvent。内部逻辑:首先调用已注册的View的OnTouchListerner接口的onTouch方法,如果onTouch方法返回false继续执行View对象的onTouchEvent方法,否则结束方法,不执行View的onTouchEvent。View对象的dispatchTouchEvent方法源码如下: