这是完整的调用日志,我们可以仔细看一下,会发现出现点击事件的日志在最后一行,而之前重���出现了ViewGroupA和ViewGroupB的事件分发。是时候揭露出完整的触发过程了。
当我们手指按下时候,会触发ACTION_DOWN的事件,这时会进行一系列的事件分发,分发规则如上面所讲,当我们手指松开的时候,会触发ACTION_UP的事件,这同样会进行一系列的事件分发,最后当这些都弄完之后,会触发onClick()事件,也就是说onClick()是事件触发的尾端。一旦前面决定不继续传递事件,则onClick()事件就不会触发。
所以这里面有一个概念叫做同一事件序列:指从手指接触屏幕的那一刻起,到手指离开屏幕的那一刻结束,在这个过程中所产生的一系列事件,这个事件序列以down事件开始,中间含有数个move事件,最终以up事件结束。
简而言之就是down-> move-> move-> move-> move......->up
而上面我们提到的onclick()如果大家看源码的话,会发现他是ACTION_UP之后通过performClick()调用的。所以如果view设置了点击事件并且能向后传递,则会最后调用onClick()。
如果仔细看上面的日志,会发现我们的打印日志的代码是这样写的Log.e("ViewTest","View onTouchEvent" + event.getAction());日志最后会出现事件的名字,在日志里面,由于getAction返回的int型的静态常量,所以是用0, 1表示,0代表ACTION_DOWN,1代表ACTION_UP,所以通过这个日志,我们可以验证这个同一事件序列这个过程。前面我放出的日志实际也是不全 我也只是把DOWN的会就放出来,日志后面还有UP的事件,处于篇幅就不全放了而已。
而针对同一事件序列 上面的例子还会说明一个特性
注意,一开始,我们直接将onTouchEvent(MotionEvent event)返回值设置为false,这样他会截断后面ACTION_UP事件的触发,通俗来讲,就是传递到VIew的DOWN事件,他都没有消耗他,没处理好他,返回了false,让他上层处理,则同一事件序列的MOVE,UP也不会给他。结合我们之前公司的例子,就是这个DOWN事件都办不好,后面也不会给他其他任务了。
我们验证一下:
08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/ViewGroupA: ViewGroupA dispatchTouchEvent0 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/ViewGroupA: ViewGroupA onInterceptTouchEvent0 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/ViewGroupB: ViewGroupB dispatchTouchEvent0 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/ViewGroupB: ViewGroupB onInterceptTouchEvent0 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/ViewTest: View dispatchTouchEvent0 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/onTouch: 我中弹了 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/ViewTest: View onTouchEvent0 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/More: 我被调用 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/ViewGroupB: ViewGroupB onTouchEvent0 08-31 07:18:40.791 16083-16083/com.byhieg.viewdipatch E/ViewGroupA: ViewGroupA onTouchEvent0这是全部的日志,确实没有UP事件。
复杂的规则下面的规则是出自《Android开发艺术探索》,我们对这些规则进行讲解,验证