Android事件分发机制

来源:互联网 发布:mac wi fi 未安装硬件 编辑:程序博客网 时间:2024/06/05 10:20

首先应该搞清楚两个问题:事件分发机制分发的是什么?怎么进行分发?

分发的是MotionEvent事件了,因而我们讨论的问题就成了当MotionEvent事件生成之后,事件是怎么传递到某一个View控件上面并且得到处理的过程;

android事件产生后的传递过程是从Activity—>Window—>ViewGroup—>View的,即隧道式传递,而View又分为不包含子 View的View以及包含子View的ViewGroup,事件产生之后首先传递到Activity上面,而Activity接着会传递到 PhoneWindow上,PhoneWindow会传递给RootView,而RootView其实就是DecorView了,接下来便是从 DecorView到View上的分发过程了,具体就可以分成ViewGroup和View的分发两种情况了;

对于ViewGroup而言,当事件分发到当前ViewGroup上面的时候,首先会调用他的dispatchTouchEvent方法,在 dispatchTouchEvent方法里面会调用onInterceptTouchEvent来判断是否要拦截当前事件,如果要拦截的话,就会调用 ViewGroup自己的onTouchEvent方法了,如果onInterceptTouchEvent返回false的话表示不拦截当前事件,那么 事件将会继续往当前ViewGroup的子View上面传递了,如果他的子View是ViewGroup的话,则重复ViewGroup事件分发过程,如 果子View就是View的话,则转到下面的View分发过程;
对于View而言,事件传递过来首先当然也是执行他的dispatchTouchEvent方法了,如果我们为当前View设置了 onTouchListener监听器的话,首先就会执行他的回调方法onTouch了,这个方法的返回值将决定事件是否要继续传递下去了,如果返回 false的话,表示事件没有被消费,还会继续传递下去,如果返回true的话,表示事件已经被消费了,不再需要向下传递了;如果返回false,那么将 会执行当前View的onTouchEvent方法,如果我们为当前View设置了onLongClickListener监听器的话,则首先会执行他的 回调方法onLongClick,和onTouch方法类似,如果该方法返回true表示事件被消费,不会继续向下传递,返回false的话,事件会继续 向下传递,为了分析,我们假定返回false,如果我们设置了onClickListener监听器的话,则会执行他的回调方法onClick,该方法是 没有返回值的,所以也是我们事件分发机制中最后执行的方法了;可以注意到的一点就是只要你的当前View是clickable或者 longclickable的,View的onTouchEvent方法默认都会返回true,也就是说对于事件传递到View上来说,系统默认是由 View来消费事件的,但是ViewGroup就不是这样了;
上面的事件分发过程只是正常情况下的,如果有这样一种情况,比如事件传递到最里层的View之后,调用该View的oonTouchEvent方法返回了 false,那么这时候事件将通过冒泡式的方式向他的父View传递,调用它父View的onTouchEvent方法,如果正好他的父View的 onTouchEvent方法也返回false的话,这个时候事件最终将会传递到Activity的onTouchEvent方法了,也就是最终就只能由 Activity自己来处理了;

事件分发机制需要注意的几点
(1):如果说除Activity之外的View都没有消费掉DOWN事件的话,那么事件将不再会传递到Activity里面的子View了,将直接由Activity自己调用自己的onTouchEvent方法来处理了;
(2):一旦一个ViewGroup决定拦截事件,那么这个事件序列剩余的部分将不再会由该ViewGroup的子View去处理了,即事件将在此 ViewGroup层停止向下传递,同时随后的事件序列将不再会调用onInterceptTouchEvent方法了;
(3):如果一个View开始处理事件但是没有消费掉DOWN事件,那么这个事件序列随后的事件将不再由该View来处理,通俗点讲就是你自己没能力就别瞎BB,要不以后的事件就都不给你了;
(4):View的onTouchEvent方法是否执行是和他的onTouchListener回调方法onTouch的返回值息息相关 的,onTouch返回false,onTouchEvent方法不执行;onTouch返回true,onTouchEvent方法执行,因为 onTouchEvent里面会执行onClick,所以造成了onClick是否执行和onTouch的返回值有了关系;

原创粉丝点击