事件分发机制,就是介绍view的click、touch、滑动等操作的事件传递流程。是很重要的一个知识体系。对于在开发中遇到的滑动失效、冲突等情况,只有了解了事件的分发机制,才能充分解决问题。
一、先要知道的一些东西
- 事件在三大层进行传递:Activity、ViewGroup、View。
- Touch事件相关细节(发生触摸的位置、时间、历史记录、手势动作等)被封装成MotionEvent对象。
- 在MotionEvent对象中包含着一系列需要分发的事件:
MotionEvent.ACTION_DOWN:按下View(所有事件的开始)
MotionEvent.ACTION_MOVE:滑动View
MotionEvent.ACTION_CANCEL:非人为原因结束本次事件
MotionEvent.ACTION_UP:抬起View(与DOWN对应) - 一次完整的MotionEvent事件,是从用户触摸屏幕到离开屏幕。整个过程的动作序列:ACTION_DOWN(1次) -> ACTION_MOVE(N次) -> ACTION_UP(1次)。
- 处理事件的三个方法:
- dispatchTouchEvent:负责分发事件;
- onInterceptT1ouchEvent:拦截事件,只在ViewGroup中存在,而且是在dispatchTouchEvent内部调用;
- onTouchEvent:处理事件;
- 三个方法不同返回值的意义:
- return true:事件就停止传递了,既不向下传递,也不向上传递,到此为止了。
- return false:事件停止向下传递,开始向上(父类)传递。也就是说不消费事件,并让事件继续往父控件的方向从下往上流动。
- return super:继续按照默认的流程继续传递。
二、事件分发的流程
- 如果中间不手动对事件进行处理和拦截,那么默认的流程是从父控件依次向子控件传递,然后再从子控件传回父控件:
从Activity---->ViewGroup--->View 从上往下调用dispatchTouchEvent方法,一直到最下面的子控件(该控件下没有子控件了)的时候,再由View--->ViewGroup--->Activity从下往上调用onTouchEvent方法。 -
明白了上面的东西,再来看下面这个经典的流程图:
二、ACTION_DOWN、ACTION_MOVE和ACTION_UP,这三个事件的传递
上面说的都是ACTION_DOWN的传递流程,ACTION_MOVE和ACTION_UP的传递流程不太一样。
只有当在onTouchEvent中返回true,对事件进行了终止时,这三者的流程不一样。其余在dispatchTouchEvent 和 onInterceptTouchEvent 中返回true、false、super,在onTouchEvent中返回false、super时ACTION_DOWN、ACTION_MOVE和ACTION_UP这三者的流程是一致的。
下面来看几张图,这里直接用了《图解 Android 事件分发机制》中的图片。这里只列出了onTouchEvent,另外两个方法和down完全一样,就不贴图了。