Android 事件分发机制总结

事件构成

在Android中,事件主要包括点按、长按、拖拽、滑动等,点按又包括单击和双击,另外还包括单指操作和多指操作。所有这些都构成了Android中的事件响应。总的来说,所有的事件都由如下三个部分作为基础:

  • 按下(ACTION_DOWN)
  • 移动(ACTION_MOVE)
  • 抬起(ACTION_UP)

所有的操作事件首先必须执行的是按下操作(ACTION_DOWN)。

Android事件分发机制

Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。

对于View:

大体流程:触摸动作发生 => 调用dispatchTouchEvent方法 => 首先调用onTouch方法

若同时满足:绑定了OnClickListener、控件可用(enabled)、onTouch方法返回true,则dispatchTouchEvent方法将直接返回true,不会调用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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public boolean dispatchTouchEvent(MotionEvent event) {
// If the event should be handled by accessibility focus first.
if (event.isTargetAccessibilityFocus()) {
// We don't have focus or no virtual descendant has it, do not handle the event.
if (!isAccessibilityFocusedViewOrHost()) {
return false;
}
// We have focus and got the event, then use normal event dispatch.
event.setTargetAccessibilityFocus(false);
}
boolean result = false;
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Defensive cleanup for new gesture
stopNestedScroll();
}
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
if (!result && mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
// Clean up after nested scrolls if this is the end of a gesture;
// also cancel it if we tried an ACTION_DOWN but we didn't want the rest
// of the gesture.
if (actionMasked == MotionEvent.ACTION_UP ||
actionMasked == MotionEvent.ACTION_CANCEL ||
(actionMasked == MotionEvent.ACTION_DOWN && !result)) {
stopNestedScroll();
}
return result;
}

否则,将会继续调用onTouchEvent方法。并且可以推断,onClick方法也是在onTouchEvent方法中调用的。

对于ViewGroup

  1. Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。
  2. 在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true代表不允许事件继续向子View传递,返回false代表不对事件进行拦截,默认返回false。
  3. 子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。

总结

  1. Android中事件按照从上到下的顺序进行层级传递,事件处理从Activity开始到ViewGroup再到View
  2. 事件传递方法包括dispatchTouchEventonTouchEventonInterceptTouchEvent,其中前两个是ViewViewGroup都有的,最后一个是只有ViewGroup才有的方法。这三个方法的作用分别是负责事件分发、事件处理、事件拦截
  3. onTouch事件要先于onClick事件执行,onTouch在事件分发方法dispatchTouchEvent中调用,而onClick在事件处理方法onTouchEvent中被调用,onTouchEvent要后于dispatchTouchEvent方法的调用
文章目录
  1. 1. 事件构成
  2. 2. Android事件分发机制
    1. 2.1. 对于View:
    2. 2.2. 对于ViewGroup
  3. 3. 总结