简述安卓事件分发、消费
学习事件分发,我花了较多的事件去研究和测试,但是最后发现,自己似乎又上当了,因为不去研究源码的话,内容确实比我们想的要少很多。
就我写文章的习惯,我也不会花大篇幅去研究人家源码,懂得在事件怎么拦截,在哪里拦截,然后怎么消费也就够了。
注:本文章“冒泡”指的是onTouchEvent事件向上传递的过程。
事件分发、消费的流程:
首先我们明确一下事件传递的流程,下面的图缺少了Activity,事件从Activity出发,然后传给Layout,也就是ViewGroup,之后是ViewGroup下面的子View,子View如果下面还有子View,那就继续传递,想总之就是这么层层嵌套,到最底下那个View。
之后还有个逆向的过程,从最底下那个View往回传递,最后返回到Activity。
假如说,在这个传递的过程中,事件被消费掉了(有可能在向下传递的时候,也有可能在向上传递的时候),比如说一个Button消费掉了事件,那么系统就会记住是Button消费了,最后执行Button中的事件。
要接触的三种对象:
跟事件分发相关的三个重要对象,他们分别有以下功能
- Activity:分发、消费。
- ViewGroup:分发、拦截,消费。
- 而View:分发、消费。
事件传递的方法调用顺序:
- Activity是事件的源头,从它的dispatchTouchEvent开始;
- 然后是ViewGroup的dispatchTouchEvent,ViewGroup的onInterceptTouchEvent;
- 如果ViewGroup还有子ViewGroup重复执行2;
- 最后执行View的dispatchTouchEvent;
- 从最底层的View开始,调用View的onTouchEvent,调用ViewGroup的onTouchEvent,最后返回到Activity。
事件的分发:dispatchTouchEvent
实际过程不要去这里拦截事件,方法名直译就是分发事件,如果我们重写了这里的代码,自然能阻止事件的传递,但是这样做明显有违作者最初的设计。
注:下面的内容就当我特别无聊做的一些测试,总结就是Super()中是事件传递的关键。
1、true:阻止分发,事件传递到本层结束,只执行 dispatchTouchEvent方法,另外两个方法不再执行,也就是说,消费的内容只能去中dispatchTouchEvent编辑了
2、false:阻止分发,事件传递到本层结束,另外两个方法不再执行,直接由上一层的onTouchEvent开始冒泡
3、先调用super.dispatchTouchEvent(ev),再return false,正常分发,正常冒泡
4、先调用super.dispatchTouchEvent(ev),再return true,正常分发,正常冒泡,分两种情况:
- 遍历到返回true的onTouchEvent,由那一层处理
- 未遍历到返回true的onTouchEvent,由当前层onTouchEvent执行
5、先调用super.dispatchTouchEvent(ev),再return false,正常分发,正常冒泡
事件拦截:onInterceptTouchEvent
看这个方法的名称,这才是拦截的方法,他会阻止事件向下传递。
1、 True 拦截,当前层的onTouchEvent可以执行到,事件不再向下执行
2、 False,super.onInterceptTouchEvent(ev),不拦截,
事件相应:onTouchEvent
通常我们会在这里编写一些其他的代码逻辑,关于我们如何消费事件的逻辑,我会把这一部分内容放到自定义View中,这里就只关注返回结果:
True:告知事件由当前层处理,他会阻止事件向上冒泡
False,super.onTouchEvent(event),不阻止冒泡
如果你想更深入地了解,我推荐你看看这几篇:
陈蒙的博客:浅尝安卓事件分发机制
郭霖: Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
鸿洋:Android View 事件分发机制 源码解析 (上)