发布于 

Android机制源码分析(一):事件分发源码浅析

碎碎念

临近毕业,在成为一名全职android开发工程师之前,重新回顾那些重要的基础知识,这是第一篇

关键流程

Android 的事件分发过程主要涉及三个方法:dispatchTouchEvent(), onInterceptTouchEvent(), 和 onTouchEvent()。事件分发过程遵循以下顺序:

  1. dispatchTouchEvent() :事件分发从根视图(通常是 ActivityFragment 的根布局)的 dispatchTouchEvent() 方法开始。此方法负责将事件传递给子视图或处理触摸事件。
  2. onInterceptTouchEvent() :对于 ViewGroup(如 LinearLayoutRelativeLayout 等),在将事件传递给子视图之前,会调用 onInterceptTouchEvent() 方法。如果此方法返回 true,则表示 ViewGroup 拦截了事件,事件将不再传递给子视图。相反,如果返回 false,事件将继续传递给子视图。
  3. onTouchEvent() :当事件到达目标视图(即没有被拦截的视图)时,会调用 onTouchEvent() 方法。此方法负责处理触摸事件。如果返回 true,表示事件已被处理,否则事件将继续向上回传给父视图。

此外,事件分发过程遵循以下规则:

  • 事件从根视图开始,沿着视图层次结构向下传递,直到找到能够处理事件的目标视图。
  • 如果某个视图(或视图组)拦截了事件,事件将不再传递给子视图。
  • 如果事件没有被处理,它将沿着视图层次结构向上回传,直到找到能够处理它的视图。

源码分析

进一步分析源码,事件分发过程涉及以下关键类和方法:

  1. ViewGroupViewGroup 是所有布局容器的基类,如 LinearLayoutRelativeLayout 等。它的 dispatchTouchEvent() 方法负责将事件传递给子视图或处理触摸事件。ViewGroup 还有一个 onInterceptTouchEvent() 方法,用于在将事件传递给子视图之前决定是否拦截事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean handled = false;
if (onFilterTouchEventForSecurity(ev)) {
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;

if (actionMasked == MotionEvent.ACTION_DOWN) {
// ...
}

if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}

// ...
}
}
return handled;
}

public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
  1. ViewView 是所有 UI 组件的基类,如 TextViewButton 等。它的 dispatchTouchEvent() 方法负责处理触摸事件。View 还有一个 onTouchEvent() 方法,用于处理触摸事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public boolean dispatchTouchEvent(MotionEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}

boolean result = false;
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// ...
}
if (!result && onTouchEvent(event)) {
result = true;
}
}

if (!result && mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
return result;
}

public boolean onTouchEvent(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
final int viewFlags = mViewFlags;
final int action = event.getAction();

// ...
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @tsparrot 创建,使用 Stellar 作为主题。