「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战」
1. 被分发的对象
按下、滑动、抬起、取消这几种事件组成了一个事件流。事件流以按下为开始,中间可能有若干次滑动,以抬起或取消作为结束。
| 事件 | 触发场景 | 触发次数(次) |
|---|---|---|
| MotionEvent.ACTION_DOWN | 按下 | 1 |
| MotionEvent.ACTION_MOVE | 滑动 | 0或多 |
| MotionEvent.ACTION_UP | 抬起 | 0或1 |
| MotionEvent.ACTION_CANCLE | 滑动超出控件边界 | 0或1 |
2. 事件分发
- 用户的按键行为->手机传感器->ViewRootImpl->DecorView->WindowCallbackWrapper->Activity->PhoneWindow->DecorView->ViewGroup*->View->程序员的代码逻辑->硬件(显示器、扬声器等)响应输出->用户感知
- ViewRootImpl是Android层逻辑起始点,用于接收来自系统底层的事件消息。相当于View管理类,本身不是View
- DecorView是Android View树的根节点,持有window对象。本身能够直接进行真正事件分发能力,但是事件分发会直接调用window,间接传递到Activity的事件分发,后续会由Activity回调DecorView的真正事件分发能力
3. Activity 的事件分发
首先会将点击事件传递到 Activity 中,具体是执行dispatchTounchEvent() 进行事件分发
所以,想要理解Android 分发机制,本质上要理解:
- Activity 点击事件的分发机制
- ViewGroup 点击事件的分发机制
- View 点击事件的分发机制
Activity.dispatchTouchEvent() 源码分析
(1) 如果 getWindow().superDispatchTouchEvent(ev) 的返回为 true , 则 Activity.dispatchTouchEvent() 就返回true , 方法结束。即 :该点击事件停止往下传递,事件传递过程结束;否则继续往下调用Activity.onTouchEvent()
// Activity.dispatchTouchEvent()
public boolean dispatchTouchEvent(MotionEvent ev) {
. . .
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
我们再看 getWindow().superDispatchTouchEvent(ev) ,getWindow() 是获取 Window 类的对象,它的唯一实现类是 PhoneWindow 类
// PhoneWindow
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
DecorView 类是 PhoneWindow 类的一个内部类,它继承 FrameLayout,是所有界面的父类,FrameLayout 是 ViewGroup 的子类,所以 DecorView 的间接父类等于 ViewGroup
// DecorView
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
Activity.onTouchEvent() 源码分析
当一个点击事件未被Activity下任何一个View接收/处理时,就会调用 Activity.onTouchEvent()
// Activity.onTouchEvent()
public boolean onTouchEvent(MotionEvent event) {
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
}
当点击事件在Window边界外会返回true