Android机制源码分析(一):事件分发源码浅析
碎碎念
临近毕业,在成为一名全职android开发工程师之前,重新回顾那些重要的基础知识,这是第一篇
关键流程
Android 的事件分发过程主要涉及三个方法:dispatchTouchEvent()
, onInterceptTouchEvent()
, 和 onTouchEvent()
。事件分发过程遵循以下顺序:
- dispatchTouchEvent() :事件分发从根视图(通常是
Activity
或 Fragment
的根布局)的 dispatchTouchEvent()
方法开始。此方法负责将事件传递给子视图或处理触摸事件。
- onInterceptTouchEvent() :对于
ViewGroup
(如 LinearLayout
、RelativeLayout
等),在将事件传递给子视图之前,会调用 onInterceptTouchEvent()
方法。如果此方法返回 true
,则表示 ViewGroup
拦截了事件,事件将不再传递给子视图。相反,如果返回 false
,事件将继续传递给子视图。
- onTouchEvent() :当事件到达目标视图(即没有被拦截的视图)时,会调用
onTouchEvent()
方法。此方法负责处理触摸事件。如果返回 true
,表示事件已被处理,否则事件将继续向上回传给父视图。
此外,事件分发过程遵循以下规则:
- 事件从根视图开始,沿着视图层次结构向下传递,直到找到能够处理事件的目标视图。
- 如果某个视图(或视图组)拦截了事件,事件将不再传递给子视图。
- 如果事件没有被处理,它将沿着视图层次结构向上回传,直到找到能够处理它的视图。
源码分析
进一步分析源码,事件分发过程涉及以下关键类和方法:
- ViewGroup :
ViewGroup
是所有布局容器的基类,如 LinearLayout
、RelativeLayout
等。它的 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); } else { intercepted = false; }
} } return handled; }
public boolean onInterceptTouchEvent(MotionEvent ev) { return false; }
|
- View :
View
是所有 UI 组件的基类,如 TextView
、Button
等。它的 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();
}
|