点击事件的传递规则
首先我们要明白这里要分析的对象就是MotionEvent,即点击事件。点击事件分发的过程由三个很重要的方法共同完成:dispatchTouchEvent,
onInterceptTouchEvent,和onTouchEvent三个方法组成。
在分析事件分发机制之前,这里先给出一些结论
- 同一个时间序列是指手指接触屏幕的那一刻起,到手指离开屏幕的那一刻结束,这个过程中阐释的一系列事件,这个时间序列以Down事件开始,中间含有数量不定的move事件,最终以up时间结束。
- 正常情况下,一个时间序列只能被一个View拦截且消耗。
- 某个View一点决定拦截,那么这个事件序列都只能由它来处理,并且它的onInterceptTouchEvent不会在被调用。
- 某个View一旦开始处理事件,如果它不消耗Action_Down事件(onTouchEvent 返回了false),那么同一事件序列中的其他事件它都不会再交给它来处理,并且事件将重新交给它的父元素去处理,即父元素的onTouchEvent会被调用。
- 如果View不消除ACTION_DOWN以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前View可以持续收到后续的事件,最终这些消失的电解事件会传递给Activity处理
事件分发机制的图解(在分析的都是ACTION_DOWN事件)
事件分发机制流程图.png图解说明:
- 1:如果事件不中断,整个事件的流向是一个U型图
- 2:dispatchTouchEvent 和 onTouchEvent 一旦return true,事件就停止传递了
- dispatchTouchEvent 和 onTouchEvent return false的时候事件都回传给父控件的onTouchEvent处理。
- onInterceptTouchEvent方法中 return true就会交给自己的onTouchEvent的处理,如果不拦截就是继续往子控件往下传
总结:
- 对于 dispatchTouchEvent,onTouchEvent,return true是终结事件传递。return false 是回溯到父View的onTouchEvent方法。
- ViewGroup 想把自己分发给自己的onTouchEvent,需要拦截器onInterceptTouchEvent方法return true 把事件拦截下来。
- ViewGroup 的拦截器onInterceptTouchEvent 默认是不拦截的,所以return super.onInterceptTouchEvent()=return false;
- View 没有拦截器,为了让View可以把事件分发给自己的onTouchEvent,View的dispatchTouchEvent默认实现(super)就是把事件分发给自己的onTouchEvent。
关于ACTION_MOVE、ACTION_UP总结
对于ACTION_MOVE、ACTION_UP总结:ACTION_DOWN事件在哪个控件消费了(return true), 那么ACTION_MOVE和ACTION_UP就会从上往下(通过dispatchTouchEvent)做事件分发往下传,就只会传到这个控件,不会继续往下传,如果ACTION_DOWN事件是在dispatchTouchEvent消费,那么事件到此为止停止传递,如果ACTION_DOWN事件是在onTouchEvent消费的,那么会把ACTION_MOVE或ACTION_UP事件传给该控件的onTouchEvent处理并结束传递。不会再往下传递!
网友评论