Android事件分发机制
概念
事件:
用户和屏幕产生交互时发生的一系列Touch事件。
Touch事件会被封装成MotionEvent对象。
事件类型:
MotionEvent.ACTION_DOWN 手指刚接触屏幕,所有事件的开始
MotionEvent.ACTION_UP 与down对应,手指从屏幕离开
MotionEvent.ACTION_MOVE 手指在屏幕上滑动
MotionEvent.ACTION_CANCEL 非人为因素取消
事件列:
从手指接触屏幕至手指离开屏幕这个过程产生的一系列事件。
一般来说从DOWN开始——若干MOVE事件——UP。若CANCEL则取消。
事件分发:
将MOTIONEVENT传递到某个具体的View并处理的过程。
事件分发的对象、顺序:
Activity——ViewGroup——View。
使用的方法:
dispatchTouchEvent():分发点击事件,在事件传递给当前View时,调用此方法。
事件(多数情况)是从Activity的dispatchTouchEvent开始的,
执行super.dispatchTouchEvent(ev),事件向下分发。
onInterceptTouchEvent():只存在于ViewGroup,判断是否拦截了某个事件。
view中不提供onInterceptTouchEvent(),默认返回True。
在ViewGroup的dispatchTouchEvent()内部调用。
onTouchEvent():dispatchTouchEvent()内部调用,处理点击事件。
事件分发流程
Activity.dispatchTouchEvent()中分发:
首先,Android的事件分发机制将事件分发至Activity.dispatchTouchEvent()
——Window.superDispatchTouchEvent(),Window是抽象类,唯一实现类为PhoneWindow
——DecorView.superDispatchTouchEvent()(所有界面的父类),
//是PhoneWindow的内部类,继承自FrameLayout。
——ViewGroup.dispatchTouchEvent()。
//也就实现了Activity——ViewGroup的事件传递。
——false——Activity.onTouchEvent()
//当一个点击事件未被Activity下任何一个View接收/处理时,就会调用该方法。
——Window.shouldCloseOnTouch()——消费或未消费。
//判断点击事件是否在边界。
——true——Activity.dispatchTouchEvent()返回true。
ViewGroup.dispatchTouchEvent()中分发
接上来到——ViewGroup.dispatchTouchEvent()
——ViewGroup.onInterceptTouchEvent()
//ViewGroup每次事件分发时,都询问onInterceptTouchEvent()是否拦截事件
——若拦截true,则不传递该事件
——调用ViewGroup父类,View的dispatchTouchEvent()
——调用自身的onTouch()—onTouchEvent()—performClick()—onClick()
——若不拦截false,继续向子View传递该事件
——遍历所有子View,寻找被点击的View
——找不到被点击的子View,也就是点击空白处
跳回View的dispatchTouchEvent()
——调用子View.dispatchTouchEvent()
//实现了ViewGroup到View的事件传递
View.dispatchTouchEvent()分发
接上来到——View.dispatchTouchEvent()
//满足三个条件View.dispatchTouchEvent()返回true,
否则返回View.onTouchEvent()
//条件1:当前控件enable
//条件2:mOnTouchListener != null,有注册Touch事件
//条件3:mOnTouchListener.onTouch(this, event),回调onTouch事件返回true,需覆写
——View.onTouchEvent()
//若可点击,判断事件类型
——若没有注册点击事件——结束
——有注册点击事件——onClick——结束
——满足条件,判断onTouch()
——返回false,View.onTouchEvent()返回true,该控件可点击—事件被接收
——返回false,View.onTouchEvent()返回false,未被消费,
传回上层ViewGroup.onTouchEvent()
——返回true,事件被消费,View.dispatchTouchEvent()返回true,结束。