View 事件体系(三)
首先先补充一下上一节的遗漏:
当一个事件产生时,他的传递顺序为:
activity -> Window(DecorView) -> View
我们追溯一下源码,会发现 activity 实现了接口 Window.Callback,事件是从这个接口的 dispatchTouchEvent 开始分发。
接着事件分发到 DecorView 也就是我们整个屏幕的根View , 我们在activity 的 onCreate() 时设置的 setContentView(),就是往 DecorView 中添加子 View,
activity dispatchTouchEvent 将事件分发给 DecorView ,再向下分发。
下面 我们看看给 view 设置 onTouchListener 会出现什么样的情况。
我们给 parent 设置 onTouchListener 并 返回 false 和打印 log:
发现几个情况:1, onTouch 触发在 onTouchEvent 之前;
2,如果 onTouch 如果返回 false, 则不会消费 ACTION_DOWN 事件,一个点击序列如果不消费 ACTION_DOWN 则不会继续消费这个点击序列的后续事件。 所以当我们在 parent 上滑动的时候 并不会再触发 onTouch。
既然如此我们在 onTouch 的时候返回 true 看看日志:
1,onTouch 返回 true ,则消费掉了点击事件,后面parent 的 onTouchEvent 并没有调用。
2,后续滑动的时候,只调用了 parent 的 dispatchTouchEvent 以及 onTouch,其他方法并没有调用:如果某个 View 一旦决定拦截,那么这一个时间序列都只能由它来处理(如果时间序列能传递给它),并且他的 onInterceptTouchEvent 不会再被调用。
第二点其实看到源码就很好理解:
只有当 actionMasked == ACTION_DOWN 的时候才会去调用 onInterceptTouchEvent 去判断是否拦截。那么还有一个判断 mFirstTouchTarget !=null.
这个 mFirstTouchTarget 是什么呢?
当 ViewGroup 不拦截事件并将事件交由子元素处理时, mFirstTouchTarget !=null ,反过来 mFirstTouchTarget = null。