总体的流程分发
Acticity —–> ViewGroup ——->View
事件分发涉及的几个方法:
1、dispatchTouchEvent
2、onInterceptTouchEvent
3、onTouchEvent
好多人都是写个dome,看看日志。努力的记住,可过不了多长时间就又忘掉了,今天我给大家准备了一个,事件分发的整体流程图
注:仔细看的话,图分为3层,从上往下依次为Activity、ViewGroup、View。
事件从左上角那个白色箭头开始,由Activity的dispatchTouchEvent做分发
箭头的上面字代表方法返回值,(return true、return false、return super.xxxxx(),super 的意思是调用父类实现。
dispatchTouchEvent和 onTouchEvent的框里有个【true---->消费】的字,表示的意思是如果方法返回true,那么代表事件就此消费,不会继续往别的地方传了,事件终止。
目前所有的图的事件是针对ACTION_DOWN的,对于ACTION_MOVE和ACTION_UP我们最后做分析。
希望大家多看几遍这个图,分发的流程会非常的清晰!
在默认的情况下,分发的流程日志如下 (此日志是只是按下操作):
有打印的日志可以看出,如何子类都不消费事件,最终会交给父类处理这事件。
下面大家在看一下默认的事件分发流程图(如果事件不被拦截):
总结:
1、如果我们没有对事件做任何拦截的情况,是从Activity —–>ViewGroup —–>View依次从上往下分发的,只到分到View,如果还有处理此事件,那么会依次View —–>ViewGroup —–>Avtivity 从下往上依次调用onTouchEvent方法传给父类。
2、dispatchTouchEvent 和onTonchEvent事件返回true,那么就会消费此事件(事件的终止,没有谁会再接收到此事件)
3、dispatchTouchEvent和onTouEvent 返回false,会回到父类的onTouchEvent
看上图深蓝色的线,对于返回false的情况,事件都是传给父控件onTouchEvent处理。
*对于dispatchEvent返回false的含义应该是:事件停止往子类分发和开始往父控件回溯(父类的onTouchEvent开始从下往上回传,直至某个onTouchEvent return true ),事件分发就像递归,return false的意思就是递归等值,然后开始回溯。
*对于onTouchEvent return false 就比较简单了,它就是不消费此事件,并让事件继续往父控件的方向从下往上流动。
4、onInterceptTouchEvent 的作用
Intercept 的意思就拦截,每个ViewGroup每次在做分发的时候,问一问拦截器要不要拦截(也就是问问自己这个事件要不要自己来处理)如果要自己处理那就在onInterceptTouchEvent方法中 return true就会交给自己的onTouchEvent的处理,如果不拦截就是继续往子控件往下传。默认是不会去拦截的,因为子View也需要这个事件,所以onInterceptTouchEvent拦截器return super.onInterceptTouchEvent()和return false是一样的,是不会拦截的,事件会继续往子View的dispatchTouchEvent传递。
5、ViewGroup和View的dispachtTouchEvent方法返回super.dispatchTouchEvent()的时候事件流走向。
首先看一下ViewGroup的dispachTouEvent时间分发流程,之前说的true是终结的传递。return false是回溯到父View的TouchEvent,然后ViewGroup通过怎样的方法才能传递到自己的onTouchEvent,方法只有一种,那就是通过InterceptTouchEvent把事件拦截下来传给自己的onTouchEvent,所以ViewGroup dispatchTouchEvent方法的super默认实现就是去调用onInterceptTouchEvent,记住这一点。 那么对于View的dispatchTouchEvent return super.dispatchTouchEvent()的时候呢事件会传到哪里呢,很遗憾View没有拦截器。但是同样的道理return true是终结。return false 是回溯会父类的onTouchEvent,怎样把事件分发给自己的onTouchEvent 处理呢,那只能return super.dispatchTouchEvent,View类的dispatchTouchEvent()方法默认实现就是能帮你调用View自己的onTouchEvent方法的。
说了这么多不知道大家明白了没有,给大家做一个总结:
*对于dispatchTouchEvent、onTouchEvent、return true是终结事件传递。return false是回溯到父View的onTouchEvent方法。
*ViewGroup想分发给自己的onTouchEvent,需要onInterceptTouchEvnet拦截到事件 return true,从而传递给自己的onTouchEvent总
*ViewGroup的onInterceptTouchEvent默认是不拦截的,所以return super.onInterceptTouchEvent()=return false;
*View没有拦截器,为了让View可以把事件分配到自己的onTouchEvent中,View的dispatchTouchEvent默认实现(super)就是把事件分发给自己的onTouchEvent。
ViewGroup和View 的dispatchTouchEvent 是做事件分发,那么这个事件可能分发出去的四个目标
1、 自己消费,终结传递。——->return true ;
2、 给自己的onTouchEvent处理——-> 调用super.dispatchTouchEvent()系统默认会去调用 onInterceptTouchEvent,在onInterceptTouchEvent return true就会去把事件分给自己的onTouchEvent处理。
3、 传给子View——>调用super.dispatchTouchEvent()默认实现会去调用 onInterceptTouchEvent 在onInterceptTouchEvent return false,就会把事件传给子类。
4、 不传给子View,事件终止往下传递,事件开始回溯,从父View的onTouchEvent开始事件从下到上回归执行每个控件的onTouchEvent——->return false;
ViewGroup和View的onTouchEvent方法是做事件处理的,那么这个事件只能有两个处理方式:
1、自己消费掉,事件终结,不在传给谁。—–>return true
2、继续从下往上传,不消费事件,让父View也能收到到这个事件 —->return false;View的默认实现是不消费的,默认super == false;
ViewGroup的onInterceptTouchEvent方法对于事件有两种情况:
1、拦截掉此事件,把事件传给自己的onTouchEvent。—–>return true
2、继续往下传,ViewGroup默认是不拦截的,return false == super.onInterceptTouchEvent
关于MOVE 和UP的事件处理
以上讲的都是ACTION_DOWN事件的传递,因为ACTION_MOVE和ACTION_UP传递的事件是不一样的,你在ACTION_DOWN的时候返回了false,后面一系列其他的action就不会在执行了。简单的说,就是当dispachTouchEvent在进行事件分发的时候,只有一个事件返回true(ACTION_DOWN)返回true,ACTION_MOVE和ACTION_UP才会收到事件,好多人都这么说,下面的例子会跟大家证明原因
1、我们在ViewGroup1 的dispatchTouchEvent 方法返回true消费这次事件
ACTION_DOWN 事件从(Activity的dispatchTouchEvent)——–> (ViewGroup1 的dispatchTouchEvent) 后结束传递,事件被消费(如下图红色的箭头代码ACTION_DOWN 事件的流向)。
//打印日志
Activity | dispatchTouchEvent --> ACTION_DOWN
ViewGroup1 | dispatchTouchEvent --> ACTION_DOWN
---->消费
在这种场景下ACTION_MOVE和ACTION_UP 将如何呢,看下面的打出来的日志
Activity | dispatchTouchEvent --> ACTION_MOVE
ViewGroup1 | dispatchTouchEvent --> ACTION_MOVE
TouchEventActivity | dispatchTouchEvent --> ACTION_UP
ViewGroup1 | dispatchTouchEvent --> ACTION_UP
下图中
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
2、我们在ViewGroup2 的dispatchTouchEvent 返回true消费这次事件
Activity | dispatchTouchEvent --> ACTION_DOWN
ViewGroup1 | dispatchTouchEvent --> ACTION_DOWN
ViewGroup1 | onInterceptTouchEvent --> ACTION_DOWN
ViewGroup2 | dispatchTouchEvent --> ACTION_DOWN
---->消费
Activity | dispatchTouchEvent --> ACTION_MOVE
ViewGroup1 | dispatchTouchEvent --> ACTION_MOVE
ViewGroup1 | onInterceptTouchEvent --> ACTION_MOVE
ViewGroup2 | dispatchTouchEvent --> ACTION_MOVE
TouchEventActivity | dispatchTouchEvent --> ACTION_UP
ViewGroup1 | dispatchTouchEvent --> ACTION_UP
ViewGroup1 | onInterceptTouchEvent --> ACTION_UP
ViewGroup2 | dispatchTouchEvent --> ACTION_UP
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
3、我们在View 的dispatchTouchEvent 返回true消费这次事件
这个我不就画图了,效果和在ViewGroup2 的dispatchTouchEvent return true的差不多,同样的收到ACTION_DOWN 的dispatchTouchEvent函数都能收到 ACTION_MOVE和ACTION_UP。
所以我们就基本可以得出结论如果在某个控件的dispatchTouchEvent 返回true消费终结事件,那么收到ACTION_DOWN 的函数也能收到 ACTION_MOVE和ACTION_UP。
4、我们在View 的onTouchEvent 返回true消费这次事件
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
5、我们在ViewGroup 2 的onTouchEvent 返回true消费这次事件
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
6、我们在ViewGroup 1 的onTouchEvent 返回true消费这次事件
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
7、我们在Activity 的onTouchEvent 返回true消费这次事件
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
8、我们在View的dispatchTouchEvent 返回false并且Activity 的onTouchEvent 返回true消费这次事件
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
9、我们在View的dispatchTouchEvent 返回false并且ViewGroup 1 的onTouchEvent 返回true消费这次事件
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
10、我们在View的dispatchTouchEvent 返回false并且在ViewGroup 2 的onTouchEvent 返回true消费这次事件
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
11、我们在ViewGroup2的dispatchTouchEvent 返回false并且在ViewGroup1 的onTouchEvent返回true消费这次事件
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
12、我们在ViewGroup2的onInterceptTouchEvent 返回true拦截此次事件并且在ViewGroup 1 的onTouchEvent返回true消费这次事件。
红色的箭头代表ACTION_DOWN 事件的流向
蓝色的箭头代表ACTION_MOVE 和 ACTION_UP 事件的流向
一下子画了好多图,还有好几种情况就不再画了,相信你也看出规律了,对于在onTouchEvent消费事件的情况:在哪个View的onTouchEvent 返回true,那么ACTION_MOVE和ACTION_UP的事件从上往下传到这个View后就不再往下传递了,而直接传给自己的onTouchEvent 并结束本次事件传递过程。
对于ACTION_MOVE、ACTION_UP总结:ACTION_DOWN事件在哪个控件消费了(return true), 那么ACTION_MOVE和ACTION_UP就会从上往下(通过dispatchTouchEvent)做事件分发往下传,就只会传到这个控件,不会继续往下传,如果ACTION_DOWN事件是在dispatchTouchEvent消费,那么事件到此为止停止传递,如果ACTION_DOWN事件是在onTouchEvent消费的,那么会把ACTION_MOVE或ACTION_UP事件传给该控件的onTouchEvent处理并结束传递。