事件分发机制
# 主要对象与方法
# 事件分发的对象
当我们手机触碰屏幕时会产生一系列的MotionEvent对象,根据触摸的情况不同,这些对象的类型也会不同。具体如下:
- ACTION_DOWN: 表示手指按下屏幕
- ACTION_MOVE: 手指在屏幕上滑动时,会产生一系列的MOVE事件
- ACTION_UP: 手指抬起,离开屏幕、
- ACTION_CANCEL:当出现异常情况事件序列被中断,会产生该类型事件
- ACTION_POINTER_DOWN: 当已经有一个手指按下的情况下,另一个手指按下会产生该事件
- ACTION_POINTER_UP: 多个手指同时按下的情况下,抬起其中一个手指会产生该事件
# 事件分发的方法
事件分发属于控件系统的一部分,主要的分发对象是viewGroup与view。而其中核心的方法有三个: dispatchTouchEvent 、onInterceptTouchEvent 、 onTouchEvent 。
那么在讲分发流程之前,先来介绍一下这三个方法。这三个方法属于view体系的类,其中 Window.CallBack 接口中包含了 dispatchTouchEvent 和 onTouchEvent 方法,Activity和Dialog都实现了 Window.CallBack 接口,因此都实现了该方法。因这三个方法经常在自定义view中被重写,以下的分析,如果没有特殊说明都是在默认方法实现的情况下。
# 重要规则
事件分发有一个很重要的原则:一个触控点的事件序列只能给一个view消费,除非发生异常情况如被viewGroup拦截 。具体到代码实现就是:消费了一个触控点事件序列的down事件的view,将持续消费该触控点事件序列接下来的所有的事件 。举个栗子:
当我手指按下屏幕时产生了一个down事件,只有一个view消费了这个down事件,那么接下来我的手指滑动屏幕产生的move事件会且仅会给这个view消费。而当我手机抬起,再按下时,这时候又会产生新的down事件,那么这个时候就会再一次去寻找消费down事件的view。所以,事件分发,是以事件序列为单位的 。
因此下面的工作流程中都是指down事件的分发 ,而不是ACTION_MOVE或ACTION_UP的分发。因为消费了down事件,意味着接下来的move和up事件都会给这个view处理,也就无所谓分发了。但同时注意事件序列是可以被viewGroup的onInterceptTouchEvent中断的,这些就属于其他的情况了。
细心的读者还会发现事件分发中包含了多点触控。在多点触控的情况下,ACTION_POINTER_DOWN与ACTION_DOWN的分发规则是不同的,具体可前往第二篇文章了解详细。ACTION_POINTER_DOWN在ACTION_DOWN的分发模型上稍作了一些修改而已,后面会详细解析
# 工作流模型
# 事件序列被中断
# 多点触控情况
# Activity的事件分发
Activity -> Window -> ViewGroup