1.什么是事件分发
(1)用户通过屏幕与手机交互的时候,每一次点击,长按,移动等都是一个事件
(2)事件分发机制:某一个事件从屏幕传递各个View,由View来使用这一事件(消费事件)或者忽略这一事件(不消费事件),这整个过程的控制
2.事件分发的基础知识
(1)分发对象:系统将事件封装为MotionEvent对象,事件分发的过程就是MotionEvent分发的过程
(2)事件类型:
按下(ACTION_DOWN),
移动(ACTION_MOVE),
抬起(ACTION_UP),
取消(ACTION_CANCEL)
(3) 事件序列:
从手指按下屏幕开始,到手指离开屏幕锁产生的一系列事件
(4)传递层级
Activity -> Window ->DecorView -> ViewGroup -> View(子View)
3.Acitvity的事件分发
(1)Activity的事件分发始于dispatchTouchEvent()方法,若该事件为按压事件,则特殊处理调用onUserInteration()方法,onUserInteration是一个抽象方法,需要重写。
(2)每一个Activity都持有一个Window对象,而Window本身为一个抽象类,其唯一实现是PhoneWindow。对于PhoneWindow持有一个DecorView的实例,作为Activity最顶层的View,DecorView继承自FrameLayout,FrameLayout继承自ViewGroup。因此,Activity通过顶层的DecorView进行事件的分发,具体调用superDispatchTouchEvent()方法,最终根据其继承关系调用到了ViewGroup里的dispatchTouchEvent()方法。故,具体的事件分发处理流程由此处理,若此处返回值为true表示事件已经被消费了,则不做后续处理,反之则调用Activity的onTouchEvent()方法处理。
(3)Activity的onTouchEvent()
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
final boolean isOutside =
event.getAction() == MotionEvent.ACTION_UP && isOutOfBounds(context, event)
|| event.getAction() == MotionEvent.ACTION_OUTSIDE;
if (mCloseOnTouchOutside && peekDecorView() != null && isOutside) {
return true;
}
return false;
}
只有当允许点击外部关闭界面、界面存在且触摸事件发生在界面外部时,才返回 true,表示应该关闭界面,这样做的好处是:
- 只有在明确允许的情况下,才响应外部点击关闭界面;
- DecorView存在时才执行关闭操作,避免异常;
- 只有点击界面外部才关闭,避免误操作。
4.ViewGroup事件分发
对于ViewGroup的事件分发而言,其核心作用为:
(1)判断该事件是否需要拦截
(2)在当前ViewGroup中找到用户真正点击的View
(3)将该事件分发到具体的View上