事件分发机制3连
Activity的事件分发机制(https://blog.csdn.net/u013728021/article/details/102826314)
ViewGroup事件分发机制(https://blog.csdn.net/u013728021/article/details/102831095)
View的事件分发机制(https://blog.csdn.net/u013728021/article/details/102826446)
MotionEvent的4种类型
事件类型 | 具体动作 |
---|---|
MotionEvent.ACTION_DOWN | 按下(所有事件的开始) |
MotionEvent.ACTION_UP | 抬起 |
MotionEvent.ACTION_MOVE | 滑动 |
MotionEvent.ACTION_CANCEL | 结束事件(非人为原因) |
事件分发的本质是将点击事件(MotionEvent)传递到某个具体的View & 处理的整个过程。
事件传递会经过 Activity -> ViewGroup -> View 三个对象。
Activity的事件分发机制
当一个点击事件发生时,事件最先传到Activity的dispatchTouchEvent()进行事件分发
dispatchTouchEvent源码分析
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback,
AutofillManager.AutofillClient {
......
public boolean dispatchTouchEvent(MotionEvent ev) {
// 一般事件列开始都是 DOWN 事件,故此处基本是true
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
// 若getWindow().superDispatchTouchEvent(ev)的返回true
// 则Activity.dispatchTouchEvent()就返回true,则方法结束。即 :该点击事件停止往下传递 & 事件传递过程结束
// 否则:继续往下调用Activity.onTouchEvent
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
/**
* 作用:实现屏保功能
* a. 该方法为空方法
* b. 当此activity在栈顶时,触屏点击按home,back,menu键等都会触发此方法
*/
public void onUserInteraction() {
}
public boolean onTouchEvent(MotionEvent event) {
// 当一个点击事件未被Activity下任何一个View接收处理时
// 应用场景:处理发生在Window边界外的触摸事件
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
// 即 只有在点击事件在Window边界外才会返回true,一般情况都返回false,分析完毕
return false;
}
......
}
getWindow().superDispatchTouchEvent(ev)
Window类是抽象类,其唯一实现类是PhoneWindow类;即此处的Window类对象 就是PhoneWindow类对象
public class PhoneWindow extends Window implements MenuBuilder.Callback {
......
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
//mDecor = 顶层View(DecorView)的实例对象
return mDecor.superDispatchTouchEvent(event);
}
//mWindow.shouldCloseOnTouch(this, event)事件
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
// 主要是对于处理边界外点击事件的判断:是否是 DOWN 事件,event的坐标是否在边界内等
if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
&& isOutOfBounds(context, event) && peekDecorView() != null) {
return true;
}
......
}
DecorView类是PhoneWindow类的一个内部类,DecorView继承自FrameLayout,是所有界面的父类,FrameLayout是ViewGroup的子类,故DecorView的间接父类ViewGroup
DecorView的superDispatchTouchEvent
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks
......
public boolean superDispatchTouchEvent(MotionEvent event) {
//调用父类的方法 = ViewGroup的dispatchTouchEvent()
//即将事件传递到ViewGroup去处理,详细请看ViewGroup的事件分发机制
return super.dispatchTouchEvent(event);
}
......
}
事件的分发是:
由Activity的dispatchTouchEvnent方法开始
–>>然后调用PhoneWindow的superDispatchTouchEvent方法
–>>接着调用DecorView的superDispatchTouchEvent方法
–>>最后还是调用ViewGroup的dispatchTouchEvent方法
具体流程如下图所示