安卓触摸事件传递机制
来源:互联网 发布:php aes解密 乱码 编辑:程序博客网 时间:2024/06/06 02:06
概述
安卓的触摸事件传递大体上是视图收到事件后进行决定是否要拦截,不拦截可以继续向内传递,拦截了不消费也可以回传给上层视图。
事件类型主要有
ACTION_DOWN(按下)
ACTION_MOVE(移动)
ACTION_UP(抬起)
ACTION_CANCEL(取消)
前面三个很好理解,共同组成一次touch事件,有时候可能没有ACTION_MOVE。ACTION_CANCEL由系统自动产生,后面会介绍到。
touch事件传递机制涉及到View中的三个方法:
1)事件分发:
dispatchTouchEvent(MotionEvent ev);
2)事件拦截:ViewGroup才有
onInterceptTouchEvent(MotionEvent ev);
3)事件响应
onTouchEvent(MotionEvent ev);
注:OnTouchListener会优先于onTouchEvent()调用,此处先不予考虑。
调用顺序是
dispatchTouchEvent() ->onInterceptTouchEvent() -> onTouchEvent()。
根据具体的返回值(都为布尔型)可能传递过程有差异。
下面具体介绍下这几个方法:
1、事件分发 dispatchTouchEvent()
事件传递到一个view时最先执行dispatchTouchEvent()方法,
- 如果dispatchTouchEvent()返回true,则事件不进行分发;
- 如果dispatchTouchEvent()返回false,则事件由上级ViewGroup的OnTouchEvent()处理;
- 如果dispatchTouchEvent()返回super.dispatchTouchEvent(),则由当前View处理,又分为:
当前是ViewGroup,传递到OnInterceptTouchEvent()决定是否要拦截
当前是普通View,直接传递到onTouchEvent()(因为ViewGroup才有OnInterceptTouchEvent()方法)。
2、事件拦截onInterceptTouchEvent()
这个方法时ViewGroup才有的,如果事件传递到当前ViewGroup,并且dispatchTouchEvent执行后确定要分发给当前view处理(返回super.dispatchTouchEvent()),则事件会传递到onInterceptTouchEvent()。
根据返回值不同,可分为两种情况:
- 返回true,则确定要拦截事件并交给当前view的onTouchEvent()处理;
- 返回false,则不进行拦截,事件传递给子视图,子视图再进行分发、拦截、响应。
super.onInterceptTouchEvent()也是返回false。
有一个特例:
当ACTION_DOWN被当前view消费后,后续(同一次按下抬起过程中)的ACTION_MOVE和ACTION_UP会直接交给当前view的onTouchEvent(),不进入onInterceptTouchEvent(),不过还是要经过分发dispatchTouchEvent()。
这里的被当前view消费包括onInterceptTouchEvent()返回true直接消费和返回false传递给子view,但是子view不处理又传递给当前的view的onTouchEvent()处理。
3、触摸事件响应onTouchEvent()
跋山(分发)涉水(拦截),事件终于传递到当前view的onTouchEvent()来进行响应了,也是really 不容易。根据不同返回值:
- 返回true,代表事件已消费,不再进行传递;
- 返回false,代表不消费此次事件,将事件传递给上一层的onTouchEvent()来处理,如果上层不消费,继续往上传递。
到这里触摸事件传递的基本流程已经讲完了,下面介绍几个特殊情况。
=======================我是分割线=========================
4、触摸事件监听器OnTouchListener
如果设置了onTouchListener,则所有传递给onTouchEvent()的事件会优先传递给onTouchListener的onTouch()方法。
onTouch() return true: 事件已消费
onTouch() return false: 事件传递给onTouchEvent()
5、重叠视图的事件传递
假设有如下布局:
<FrameLayout android:id="@+id/parentA" android:layout_width="match_parent" android:layout_height="match_parent"> <TestView android:id="@+id/childB" android:layout_width="match_parent" android:layout_height="match_parent"/> <TextView android:id="@+id/childA" android:layout_width="match_parent" android:layout_height="50dp" /> </FrameLayout>
FrameLayout parentA中有两个子视图, childA和childB,A覆盖于B之上(z轴重叠)。
注:接下来的分析都假设parentA不进行事件拦截。
当触摸childA所在区域,ACTION_DOWN事件先从parentA向childA传递。
如果事件成功被childA消费(onTouchEvent() 返回true),则以后的ACTION_MOVE和ACTION_UP也是传递给childA。
反之childA没有消费该ACTION_DOWN事件的话,则该事件继续传递给childA下面的childB,如果childB消费了ACTION_DOWN,则以后的ACTION_MOVE和ACTION_UP也是传递给childB。
总结:当视图发生重叠时,后续ACTION_MOVE和ACTION_UP的接收对象与ACTION_DOWN的接收对象保持一致。
6、ACTION_CANCEL何时产生
ACTION_CANCEL与前面介绍的几种事件不一样, 不由触摸直接产生,通常不会遇到。
假设父视图parentA中有子视图childA,按下后假设ACTION_DOWN被childA消费了, 之后parentA拦截了ACTION_MOVE和ACTION_UP,则childA会收到ACTION_CANCEL事件(从事件分发dispatchTouchEvent()开始),产生该ACTION_CANCEL事件的ACTION_MOVE或者ACTION_UP事件也会停止,不传递到parentA的onTouchEvent(),即使他已经拦截了。
但是后续如果还有move或者up事件,parentA拦截下来还是会传递到onTouchEvent(),通常move事件是连续多次的不会有影响,但是如果一次触摸只有ACTION_DOWN和ACTION_UP,那么刚才这种情况就会导致ACTION_UP出发ACTION_CANCEL,而不被正确处理,需要注意。
总结:
一个视图处理了ACTION_DOWN事件,而没有收到后续的ACTION_MOVE和ACTION_UP(可能被拦截了),那么该视图就会收到ACTION_CANCEL,并且触发ACTION_CANCEL的MOVE或者UP也会立即停止,不继续传递不被消费。
写在最后
安卓touch事件传递流程还是很清晰的,最好学习的方式就是自己定义几个view重写
dispatchTouchEvent(MotionEvent ev);
onInterceptTouchEvent(MotionEvent ev);
onTouchEvent(MotionEvent ev);
这个几个方法,分别对里面的ACTION_DOWN,ACTION_MOVE,ACTION_UP进行不同处理,返回不同值,打出log来分析。
在自定义功能复杂一点的View时,对touch事件的理解还是比较重要的,
还在学习,希望对大家有所帮助。
END.
- 安卓触摸事件传递机制
- 安卓事件传递机制
- 安卓事件传递机制
- Android 触摸事件传递机制
- Android 触摸事件传递机制
- 触摸事件的传递机制
- Android 触摸事件传递机制
- Android 触摸事件传递机制
- Android 触摸事件传递机制
- Android 触摸事件传递机制
- android 触摸事件传递机制
- 触摸事件的传递机制
- android触摸事件传递机制
- Android 触摸事件传递机制
- Android触摸事件传递机制
- Android触摸事件传递机制
- Android 触摸事件传递机制
- Android 触摸事件传递机制
- sqoop-1.4.6使用指南
- 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)
- 验证码
- 高斯消元总结
- 2017 360 软件开发 小B乘车看风景问题解答 java
- 安卓触摸事件传递机制
- 如何解决高并发 代码
- WCF与Web API 区别(应用场景)
- 深度学习之caffe Data Layers
- POJ1061青蛙的约会(扩展欧几里得)
- bzoj 3899 仙人掌树的同构 仙人掌 树hash
- ucos_II的基本概念
- 关于svn在androidstudio中配置的问题
- 6款漂亮HTML CSS样式用户留言表单