Android View事件分发机制
触摸事件的类型
触摸事件对应的是MotionEvent类,事件类型主要有如下三种
- ACTION_DOWN:按下操作
- ACTION_MOVE:按下屏幕后滑动操作
- ACTION_UP:离开屏幕操作
注:ACTION_DOWN和ACTION_UP这两个操作是一定存在的,ACTION_MOVE操作是否存在要视情况而定。
事件传递的三个阶段
事件传递的三个阶段如下:
分发(Dispatch)
对应 dispatchTouchEvent 方法,方法原型如下
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
返回 true 表示事件被当前视图消费掉;
返回 super.dispatchTouchEvent(event) 表示继续分发该事件。
注:如果当前视图是ViewGroup及其子类,则会调用下面的拦截方法,判断是否拦截该事件。(原因下面有介绍)
拦截(Intercept)
对应 onInterceptTouchEvent 方法,该方法只存在于ViewGroup 及其子类中,在View 和 Activity 中不存在。方法原型如下:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
返回 true 表示拦截该事件,同时让自身的onTouchEvent方法进行消费;
返回 super.onIntercepTouchEvent(ev)表示不拦截事件,继续传递给子视图。
消费(Consume)
对应 onToouchEvent 方法,方法原型如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
返回 true 表示当前视图处理该事件;
返回 false 表当前视图不处理该事件,会传递给父视图的 onTouchEvent方法进行处理。
注:在Android 系统中,只有View、Activity、ViewGroup才有事件传递。只有ViewGroup才有拦截方法。
View 的事件传递机制
虽然 ViewGroup 是View的子类,但是这里所说的View 专指除ViewGroup 外的View 控件,如:TextView等 。
原理:遍历父控件的子元素,判断子控件是否能够接收点击事件,如果子元素能接收到点击事件,则交由子元素来处理。
结论
01、触摸事件从 dispatchTouchEvent 开始,如果无人为干预(默认返回super),则事件将从外到内依次传递,直到最内层View 的onTouchEvent 处理,返回true;如果处理不了 返回 false ,则事件依次向外层传递。
02、如果事件向内层传递有人为干预,则事件会提前消费,最内层不会收到事件。
03、View 控件的事件触发顺序,先执行 onTouch 方法,然后才执行 onClick 方法。如果 onTouch 返回true ,则 onClick 方法不会执行,事件不会继续传递;如果返回false,则事件继续传递。
ViewGroup 的事件传递机制
ViewGroup 是作为View控件的容器存在的,如:LinearLayout、ListView等。
结论:
传递流程同 View 的事件传递,只是多了onIntercepTouchEvent 方法对事件的拦截,如果返回 true 拦截事件,不会继续传递;如果返回 false或者 super 则事件正常传递。