简介
android 事件分发是指将屏幕点击事件分发至View的过程。当我点击屏幕时,会生成一个MotionEvent事件,交由ViewRootImpl进行分发到关联自身的一个控件树中。
主要的分发流程
在一个Acitivty界面中的分发流程
- ViewRootImpl会将MotionEvent事件交由关联控件树的根View即DecorView。
- DecorView会将点击事件回调到Activity中,
- Activity会将点击事件交由PhoneWindow分发,
- phoneWindow会将点击事件点击事件交由DecorView的父类的DispatchTouchEvent方法进行分发
- 在dispatchTouchEvent方法中会执行拦截,寻找目标子控件,派发事件一系列操作(由于一个屏幕点击事件正常情况下只能有一个View消费,所以目标View消费了Down事件则后续事件都会由此View消费)。
- 首先ViewGroup中进行事件是否需要分发给子View的判断,若分发则会通过onInterceptTouchEvent判断是否进行拦截操作,
- 第二步进行目标子控件寻找,如果找到则会创建一个TouchTarget
- 第三步判断是否存在TouchTarget,若存在则直接分发给目标子控件,若不存在则自己消费,重复6到8步直到时间到达View控件
- 当事件到达View时,View会先判断是否存在onTouchListener,若存在则将事件交由listener处理,若不存在则会交由自身的TouchEvent方法
- TouchEvent中会进行点击事件或者长按事件的判断,若存在其监听则会交由其处理。
- 此流程中只要一处消费了点击事件则此流程中断,若没消费则会逆向调用onTouchEvent方法直到交由Activity的OnTouchEvent方法。
触摸事件的类别
一个触摸事件有多种状态
- ACTION_DOWN:当手指按下的时候会产生此事件
- ACTION_MOVE:当手指移动时会产生此事件
- ACTION_UP:当手指抬起时会产生此事件
- ACTION_CANCEL:当手指移除目标View的时候或者父控件拦截了MOVE事件时会产生此事件
- ACTION_POINTER_DOWN:此事件会在ViewGroup中存在,当多指触摸时,第二个及以后的手指按下产生的事件
- ACTION_POINTER_UP:此事件会在ViewGroup中存在,当多指触摸时,屏幕上最后一个手指之前的手指抬起会触发此事件。
多指触摸的事件分发
MotionEvent中包含当前屏幕触控点的所有信息,他的内部用了一个数组来存储不同的触控id所对应的坐标数值。
当一个View消费了DOWN事件后,ViewGroup会为该View创建一个TouchTarget,其包含了该View的实例以及触控id,此触控ID可以是多个,因此一个View可以接收多个触控点信息。
当ViewGroup接收到一个多点触控的MotionEvent时,其会根据触控点信息分别找到目标View将其拆分为多个MotionEvent然后分别发送至目标View。