1.点击事件传递规则
1.1 ViewGroup 中逻辑
对于一个根 ViewGroup,点击事件产生后,首先传递给它,调用它的 dispatchTouchEvent 方法
如果这个 ViewGroup 的 onInterceptTouchEvent 返回 true ,表示它要拦截该事件,接着事件会交由 该 ViewGroup 处理,即调用 它的 onTouchEvent 方法
如果 onInterceptTouchEvent 返回 false,事件会传递给它的 子View,接着 子View 调用它的 dispatchTouchEvent 方法。
1.2 onTouchEvent 返回 false
事件传递,遵循规则如下:Activity –> Window –> View(*View)
如果一个 View(无子View) 的 onTouchEvent 返回 false,那么它父容器的 onTouchEvent 会被调用,一次类推,如果所有的元素都不处理该事件,那么这个事件最终会传给 Activity 处理,即 Activity 的 ontouchEvent 会被调用。
1.3 总结,更好地理解整个传递机制
2.*View对点击事件的分发过程
2.1 大致逻辑
如果事件能够传递给当前View,那么此方法一定会被调用
返回结果受当前View 的 onTouchEvent 和下级 View 的 dispatchTouchEvent 方法的影响,表示是否消耗当前事件
2.2 当前View是否拦截点击事件源码分析
结论
当ViewGroup 决定拦截事件后,那么后续的点击事件都会交给它处理并且不再调用它的 onInterceptTouchEvent 方法
onInterceptTouchEvent 不是每次事件都会被调用,如果想提前处理所有的点击事件,要选择 dispatchTouchEvent 方法,只要能传递给当前 View ,他每次都会被调用
FLAG_DISALLOW_INTERCEPT 可以用于处理滑动冲突
2.3 ViewGroup 不拦截时事件分发的源码
首先会遍历 ViewGroup 的所有子元素,然后判断子元素是否可以接收点击事件(子元素是否在播动画 && 点击事件的坐标是否落在子元素的区域内),如果某个子元素满足这两个条件,事件就会传递给它来处理。
如果子元素的 dispatchTouchEvent 返回 true,暂不考虑如何在子元素内部怎么分发,mFirstTouchTarget 就会被赋值同时跳出 for 循环
如果子元素的 dispatchTouchEvent 返回 false,ViewGroup 就会把事件分发给下一个子元素(如果有)
- Activity.dispatchTouchEvent 返回 true |fasle 事件只在 Activity 的 dispatchTouchEvent 进行处理。
如果遍历所有的子元素后事件都没有被合适的处理,这包含两种情况,1:ViewGroup 没有子元素,2:子元素处理了点击事件,但是 dispatchTouchEvent 中返回了 false (一般是因为子元素在 onTouchEvent 中返回了 false),这就验证了下面这句话:
另外,在这两种情况下,ViewGroup 会自己处理点击事件
注意第三个参数 child 为 null , 2.3 一开始的代码里有分析,它会调用
super.dispatchTouchEvent(event)
很显然,这里会转到 View 的 dispatchTouchEvent 方法,即点击事件交由 View 来处理
View.dispatchTouchEvent 返回super.dispatchTouchEvent(ev); 事件会传递给当前View的 onTouchEvent 进行处理;
ViewGroup.dispatchTouchEvent 返回super.dispatchTouchEvent(ev); 事件会传递给当前ViewGroup的 onInterceptTouchEvent 进行处理;
3. View(不含ViewGroup)处理事件逻辑
右侧的是 onTouchEvent 中的 onClick 方法,也在下面
onTouchEvent 方法中的逻辑:
4.事件拦截 onInterceptTouchEvent
onInterceptTouchEvent 的事件拦截逻辑如下:
如果 onInterceptTouchEvent 返回 true,则表示将事件会被拦截,事件最终在当前ViewGroup的 onTouchEvent 进行处理;
如果 onInterceptTouchEvent 返回 false,则表示将事件没被拦截,事件会被传递到子 View上,再由子 View 的 dispatchTouchEvent来开始这个事件的分发;
- 如果 onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件默认不会被拦截,处理方式同返回false一样。
5.事件响应 onTouchEvent
onTouchEvent 的事件响应逻辑如下:
如果 onTouchEvent返回了 true 则会接收并消费该事件。
-
如果 onTouchEvent返回了 false 那么这个事件会从当前 View 向上传递,并且都是由上层 View 的 onTouchEvent 来接收,
如果传递到上面的 onTouchEvent 也返回 false,这个事件就会“消失”,而且接收不到下一次事件。
-
如果返回 super.onTouchEvent(ev);
Activity.super.onTouchEvent(ev); 默认 返回 false
ViewGroup.super.onTouchEvent(ev); 默认 返回 false
View.super.onTouchEvent(ev); Clickable 或 LongClickable 一个为true,就默认 返回 true,不管它是不是 disable 状态