在网上关于事件分发机制的文章有很多,有些观点认为事件是最先被外层的View捕获到然后在分发,有些观点认为事件的分发是从Activity开始的。既然有不同的观点,只好自己做一些实验,来验证。主要是想看一下Android事件分发(dispatchTouchEvent),拦截(onInterceptTouchEvent),处理(onTouchEvent)的顺序。下面是我的一些探究,现发布出来供大家一起学习探讨。
我们首先定义这样一个视图层次,三个自定义ViewGroup ,一个自定义View。重写了自定义ViewGroup的dispatchTouchEvent,onInterceptTouchEvent 和 onTouchEvent方法,重写了自定义View的dispatchTouchEvent和onTouchEvent方法,通过打印log的方式查看事件流的顺序。
layer我对以下几种情况的事件流的分发做了一些实验:
1. 在三层自定义ViewGruop不做任何拦截处理:在一次点击事件之后,查看事件流
event flow我们可以看到事件流是这样的: FirstLayer -->SecondLayer-->ThirdLayer-->FourthButton,在ViewGroup中会先调用dispatchTouchEvent然后调用onInterceptTouchEvent。
onInterceptTouchEvent是ViewGroup才有的方法,我们通过查看ViewGroup发现onInterceptTouchEvent是在dispatchTouchEvent中被调用,所有onInterceptTouchEvent都是在dispatchTouchEvent后出现。onTouchEvent也是在dispatchTouchEvent中调用。
2.如果我们重写dispatchTouchEvent,并且不去调用父类中的dispathTouchEvent方法时,事件拦截(onInterptTouchEvent)和事件处理(onTouchEvent)会失效。重写FirstLayer中的dispathTouchEvent方法,SecondLayer和ThridLayer中的方法就不会被调用。重写ThirdLayer的dispatchTouchEvent方法后,对FirstLayer和SecondLayer没有影响,这也说明了事件分发的方向。
3.重写onInterptTouchEvent
onInterptTouchEvent只存在与ViewGroup中,一个ViewGroup想要处理一个事件时需要先重写onInterptTouchEvent方法让他返回ture。在SecondLayer中我想要对move事件作拦截后,在拦截后move事件最终会转变成up或cancel事件,之后up和cancel事件都会直接交给这个SecondLayer的onTouchEvent处理,而不用在调用onInterptTouchEvent。
4.重写onTouchEvent
onTouchEvent中一般是对事件处理的具体逻辑,在onInterptTouchEvent中拦截后在onTouchEvent中去处理,如果他返回true,就表示这次事件处理完成,如果返回false这次事件会返回给上一层处理。
如果我在ThirdLayer中在onInterptTouchEvent中返回true拦截事件,在onTouchEvent中返回false就表示ThirdLayer不会处理这次事件,这次事件会返回给SecondLayer处理。之后的事件也会给SecondLayer处理,不会再分发给ThirdLayer。
总结:
一次Down事件分发顺序:FirstLayer-->SecondLayer-->ThirdLayer-->FourthButton,如果FourthButton消费Down事件,并且前面ViewGroup不再进行拦截,后面的Up或Cancle事件都会直接交给FourthButton来处理。
FourthButton中不处理事件:在FouthButton中onTouchEvent中返回false,表示事件没有处理,事件会返回给ThirdLayer去做处理,如果ThirdLayer也不做处理就会继续返回。
在ThirdLayer中拦截事件但不处理:在ThirdLayer中onInterptTouchEvent中返回true,会调用onTouchEvent,在onTouchEvent中返回false,事件会返回到SecondLayer处理,以后事件也是直接交给SecondLayer处理。
ps:第一次想要写好一篇技术文章,写文章不容易。。。
网友评论