View事件分发

场景:粉色为View,灰色为ViewGroup,淡黄色为ViewgroupMax,给粉色View在MainActivity里绑定了一个onClick事件,View响应会打印Log——“响应点击事件”。
粉色为View,灰色为ViewGroup,淡黄色为ViewGroupMax

正常情况下:当父容器不拦截,View消耗事件时。
在这里插入图片描述
得出如下图:
在这里插入图片描述
可以看出,正常一个点击事件的传递是先调用父容器的分发(dispatch…)方法,然后调用拦截(onIntercept…)方法,此时如果拦截返回为true则不继续往下传递,若为false则调用子View的分发方法(disPatch…)然后继续传递直到事件被拦截或者到最底层的一个View,这时再回传dispatch方法返回值。

注意:
1.View没有拦截方法,即没有onInterceptTouchEvent方法;
2.MainActivity也没有拦截方法,即没有onInterceptTouchEvent方法;
3.dispatchTouchEvent方法的返回值由onInterceptTouchEvent方法和onTouchEvent方法的返回值共同决定。

再看下面这几种情况:
1.ViewGroup拦截方法直接返回true,但是onTouchEvent并无操作。
结果:会先从上往下传,传到ViewGroup的onTouchEvent,并返回flase,然后向上传递,依次调用父容器的onTouchEven方法,若被消耗则dispatch返回true,并停止调用父容器的onTouchEvnet方法。
2.ViewGroup拦截方法直接返回true,并且onTouchEvnet也返回true。
结果:不会依次调用父容器的onTouchEvent事件,并且dispatchTouchEvent会从当前层向上返回true.
3.ViewGroup拦截方法默认返回(flase),View的onTouchEvent返回flase。
结果:从View开始依次调用父容器的onTouchEvent方法(默认false),并且从View开始的 dispatchTouchEvent方法返回false.

点击事件流程

答:点击事件的事件分发其实就是对MontionEvent事件的分发过程。它的分发过程需要三个重要方法来共同完成:dispatchTouchEvent、onInterceptTouchEvnet和onTouchEvent。dispatchTouchEvent方法是用来分发事件的方法,onInterceptTouchEvent方法是用来判断是否拦截当前事件的方法,onTouchEvent方法是用来决定是否消耗当前事件的方法。点击事件对于ViewGroup来说:它会先经过它的dispatchTouchEvent方法,然后通过super.dispatchTouchEVent方法调用了自己的onInterceptTouchEvent方法来判断是否拦截当前事件,拦截则会调用自己的onTouchEvent方法,不拦截则继续向下传递,调用子View的dispatchTouchEvent方法,直到消耗掉。如果没有被消耗掉也就是到最底层View了,最低层View没有拦截方法也就是没有onInterceptTouchEvent方法,但是它的onTouchEvent方法返回了false,这时会依次像上传递调用父容器的onTouchEven方法,直到OnTouchEvnet方法返回true被消耗掉。
这里还有一些需要注意的:
第一,从手指接触屏幕那一刻到手指离开屏幕那一刻结束为一完整的事件序列。
第二,一个事件序列只能被一个View拦截并消耗掉,因为某个View一旦拦截了某次事件,那么同一序列事件内所有事件都会交由这个View处理,不会出现,同一事件分别由两个View处理。因为系统会把它的引用保存,并且之后不会再调用View的onInterceptToucEvent方法再次询问它是否拦截。
第三,某个View一旦开始处理时间,如果它不消耗ACTION_DOWN事件(onTouchEvent方法返回false),那么同一事件序列中的其他事件都不会交给它处理了,并且会向上依次调用onTouchEvnet方法。
第四,如果View不消耗ACTION_DOWN以外的同一事件序列的其他事件,则这个点击事件会消失,此时不会调用父的onTouchEvent方法,并且当前View可以收到后续事件,这些消失的点击事件最后会传递给Activity处理。
第五,View没有拦截方法(onIntercepteTouchEvent方法),所以传到View就会调用它的onTouchEvent方法,并且它的onTouchEvent方法默认返回true,除非它是不可点击的(即clickable和longClickable同时为false),longClickable属性默认为false,clickable属性要分情况,比如Button是true,TextView就是false。但是View的enable属性不会影响onTouchEvent方法的返回值,也就是说一个View是disable的但只要它的clickable或者longClickable有一个为true,它的onTouchEvent方法就会返回true.onClick方法发生的前提是View是可点击的,并且收到了down和up事件。
第六,通过requestDisallowTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是除了ACTION_DOWN事件。
还有一点需要注意:onTouch方法优先级>onTouchEvent方法>onClick方法。

还有一些特殊情况,例如出现滑动冲突时在解决时,改变了事件的传递方向。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值