在我们实际的项目中,涉及到手势的操作很多,这就需要我们对Android的事件有一定的了解,才能设计出好的手势。本文就对Android中的事件分发做一些简单的介绍。
1、Android中事件的基本概念
1.1、事件分发的对象
事件分发的对象就是事件,当我们触摸屏幕的时候就会触发一系列的事件。
Touch事件相关细节(发生触摸的位置、时间、历史记录、手势动作等)被封装成MotionEvent对象。
1.2、事件的种类
Android中的事件分为4类:
- MotionEvent.ACTION_DOWN:按下View(所有事件的开始)
- MotionEvent.ACTION_MOVE:滑动View
- MotionEvent.ACTION_CANCEL:非人为原因结束本次事件(比如滑出手机屏幕外)
- MotionEvent.ACTION_UP:抬起View(与DOWN对应)
每次使用的时候都会组合触发这些事件,以down事件开始,以up或者cancel事件结束,如下图所示:
1.3、事件传递的对象
在Android中,事件是在Activty、ViewGroup、View之间相互传递的。
当我们点击屏幕,MotionEvent在这些对象之间传递,就叫做事件分发。
2、事件分发的过程
2.1、相关方法
在完整分析事件分发过程之前,先来看下事件分发的相关方法
- dispatchTouchEvent():Activity、ViewGroup、View中都存在该方法,是用来分发事件的,当触摸屏幕,就会触发Activity的此方法
- onInterceptTouchEvent():只存在于ViewGroup,是用来拦截事件的,在ViewGroup的dispatchTouchEvent()内部触发
- onTouchEvent(): Activity、ViewGroup、View中都存在该方法,是用来处理事件的,在dispatchTouchEvent内部触发
这些方法都会返回一个boolean变量,我们来对不同传递对象的各方法进行一个归纳总结:
Activity
dispatchTouchEvent()
- super:调用ViewGroup的dispatchTouchEvent()方法
- true/false:消费事件,结束当前事件的传递
onTouchEvent()
- 不论返回什么,都会结束
ViewGroup
dispatchTouchEvent()
- super:传递到当前ViewGroup的onInterceptTouchEvent()中
- false:不消费,事件向上传递,传递到Activity的onTouchEvent()
- true:消费事件,结束
onInterceptTouchEvent()
- super/false:不拦截事件,事件向下传递,传递到子View的dispatchTouchEvent()
- true:拦截事件,传递到当前ViewGroup的onTouchEvent()中
onTouchEvent()
- super/false:不消费事件,事件向上传递,传递到Activity的onTouchEvent()中,如果返回false,当前ViewGroup不再接收该事件队列的后续事件
- true:消费事件,结束
View
dispatchTouchEvent()
- super:传递到当前View的onTouchEvent()中
- false:不消费,事件向上传递,传递到ViewGroup的onTouchEvent()
- true:消费事件,结束
onTouchEvent
- super:这个针对不同的View,情况不太一样,如果当前View是clickable的(如Button),则消费事件,否则向上传递到ViewGroup的onTouchEvent()中
- false:不消费事件,向上传递到ViewGroup的onTouchEvent()中,该View不再接收该事件队列的后续事件
- true:消费事件,结束
具体看下表:
2.2、具体流程
注意看箭头的方向,默认实现并不一定是单纯的true或者false,是属于第三种情况,会调用到别的传递对象里的方法。
这里对上图作各个情况的梳理,见下面的流程图:
3、源码分析
这里简单做点源码分析,如果感兴趣的话,读者可以自行利用工具查看源码
一个事件首先触发的是Activity的dispatchTouchEvent()方法