欢迎访问我的博客:Android 解忧杂货店
MotionEvent — 点击事件
所有 Touch 事件都被封装成了 MotionEvent 对象,包括 Touch 的位置、时间、历史记录以及第几个手指(多指触摸)等。
当一个 MotionEvent 产生后,系统需要把这个事件传递给一个具体的View,而这个传递的过程就是分发过程。
事件类型
ACTION_DOWN : 手指刚接触屏幕
ACTION_MOVE : 手指在屏幕上移动
ACTION_UP : 手指从屏幕上松开的一瞬间
ACTION_POINTER_DOWN : (屏幕上已有触控点,再按下其他触控点)
ACTION_POINTER_UP :(屏幕上当前有多个触控点,松开非最后一个点)
ACTION_CANCEL :
每个事件都是以 ACTION_DOWN 开始 ACTION_UP 结束。
事件处理
处理事件的方法介绍:
dispatchTouchEvent(MotionEvent ev)
用来进行事件的分发。如果事件能够传递给当前 View,那么此方法一定会被调用,返回结果受当前 View 的 onTouchEvent() 和下级 View 的 dispatchTouchEvent()方法影响,表示是否消耗当前事件。
onInterceptTouchEvent(MotionEvent event)
在上述方法( dispatchTouchEvent() )的内部调用,用来判断是否拦截某个事件,如果当前 View 拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件。
onTouchEvent(MotionEvent event)
在 dispatchTouchEvent 方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次接受到事件。
传递流程
Activity ——> ViewGroup (父View) ——> View (子View,即目标View)
一图胜千言
(1) View 不处理事件流程图
(2) View 处理事件流程图
(3) View 事件被拦截的情况:
下面开始详解:
触摸事件是一连串ACTION_DOWN,ACTION_MOVE..MOVE…MOVE、最后ACTION_UP,触摸事件还有ACTION_CANCEL事件。
事件都是从ACTION_DOWN开始的,Activity的dispatchTouchEvent()首先接收到ACTION_DOWN,执行super.dispatchTouchEvent(ev),事件向下分发。
dispatchTouchEvent()返回true,后续事件(ACTION_MOVE、ACTION_UP)会再传递,如果返回false,dispatchTouchEvent()就接收不到ACTION_UP、ACTION_MOVE。
情形 1 :ACTION_DOWN 事件没有被消费 流程图:
情形 2 :ACTION_DOWN 被目标 View 消费:
情形 2.1 后续ACTION_MOVE和UP在不被拦截的情况下都会去找VIEW
情形 2.2 后续的事件(ACTION_MOVE和UP)被拦截了
情形 3 ACTION_DOWN一开始就被父View(ViewGroup)拦截
android中的Touch事件都是从ACTION_DOWN开始的:
- 单手指操作:ACTION_DOWN—ACTION_MOVE—-ACTION_UP
- 多手指操作:ACTION_DOWN—ACTION_POINTER_DOWN—ACTION_MOVE–ACTION_POINTER_UP—ACTION_UP.
总结:
事件从 Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的 View(ViewGroup)开始一直往下(子 View)传递。子 View 可以通过 onTouchEvent()对事件进行处理。
事件由父 View(ViewGroup)传递给子 View,ViewGroup 可以通过 onInterceptTouchEvent()对事件做拦截,停止其往下传递。
如果事件从上往下传递过程中一直没有被停止,且最底层子 View 没有消费事件,事件会反向往上传递,这时父 View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到 Activity 的 onTouchEvent()函数。
如果 View 没有对 ACTION_DOWN 进行消费,之后的其他事件不会传递过来。
OnTouchListener 优先于 onTouchEvent()对事件进行消费。
上面的消费即表示相应函数返回值为 true。
参考博文:
Android 触控事件解析(Mastering the Android Touch System)
Android中的dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()