AndroidViewGroup事件分发机制与dispatchTouchEvent源码剖析
2023-09-13 05:06:56
导论
Android的事件分发机制是应用程序响应用户输入的基础。理解这一机制对于开发高质量的Android应用程序至关重要。本文将深入分析Android ViewGroup的事件分发机制,重点剖析dispatchTouchEvent源码,以便更好地理解Android事件处理的原理。
ViewGroup的事件分发机制
ViewGroup是Android应用程序中布局的基础组件。它负责管理其子视图的布局和显示,并处理触摸事件和其他输入事件。ViewGroup的事件分发机制主要由dispatchTouchEvent方法实现。
dispatchTouchEvent方法
dispatchTouchEvent方法是ViewGroup处理触摸事件的入口。当触摸事件发生时,系统会调用该方法,并传递触摸事件对象作为参数。该方法首先调用onUserInteraction()方法,然后循环遍历子视图,并调用子视图的dispatchTouchEvent方法。如果子视图处理了触摸事件,则该方法返回true,否则返回false。
public boolean dispatchTouchEvent(MotionEvent ev) {
onUserInteraction();
boolean handled = false;
if (mFirstTouchTime == -1) {
long now = SystemClock.uptimeMillis();
mFirstTouchTime = now;
mLastTouchTime = now;
}
...
for (int i = 0; i < mChildrenCount; i++) {
final View child = mChildren[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
&& child.getAlpha() > 0.5f && child.isTouchEventEnabled()) {
if (!child.isDuplicateParentStateEnabled()) {
child.dispatchTouchEvent(ev);
} else if (ev.getActionMasked() != MotionEvent.ACTION_CANCEL) {
final float x = ev.getX();
final float y = ev.getY();
child.mLeft = (int) x;
child.mTop = (int) y;
child.mRight = (int) (x + child.getMeasuredWidth());
child.mBottom = (int) (y + child.getMeasuredHeight());
child.dispatchTouchEvent(ev);
}
handled = true;
}
}
...
mLastTouchTime = SystemClock.uptimeMillis();
return handled;
}
onUserInteraction()方法
onUserInteraction()方法是一个空方法,在dispatchTouchEvent方法中被调用。该方法用于重置用户的触摸超时时间,防止用户在长时间不触摸屏幕后被注销。
DecorView
DecorView是Activity的根视图。它继承了FrameLayout,并负责管理Activity的窗口内容。DecorView的dispatchTouchEvent方法会将触摸事件传递给Activity的根布局。
源码分析
public boolean dispatchTouchEvent(MotionEvent ev) {
onUserInteraction();
boolean handled = false;
if (mFirstTouchTime == -1) {
long now = SystemClock.uptimeMillis();
mFirstTouchTime = now;
mLastTouchTime = now;
}
...
for (int i = 0; i < mChildrenCount; i++) {
final View child = mChildren[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
&& child.getAlpha() > 0.5f && child.isTouchEventEnabled()) {
if (!child.isDuplicateParentStateEnabled()) {
child.dispatchTouchEvent(ev);
} else if (ev.getActionMasked() != MotionEvent.ACTION_CANCEL) {
final float x = ev.getX();
final float y = ev.getY();
child.mLeft = (int) x;
child.mTop = (int) y;
child.mRight = (int) (x + child.getMeasuredWidth());
child.mBottom = (int) (y + child.getMeasuredHeight());
child.dispatchTouchEvent(ev);
}
handled = true;
}
}
...
mLastTouchTime = SystemClock.uptimeMillis();
return handled;
}
代码解析
dispatchTouchEvent方法首先调用onUserInteraction()方法,然后循环遍历子视图,并调用子视图的dispatchTouchEvent方法。如果子视图处理了触摸事件,则该方法返回true,否则返回false。
在循环中,该方法首先检查子视图是否可见、是否透明以及是否启用了触摸事件。如果子视图满足这些条件,则该方法会调用子视图的dispatchTouchEvent方法。如果子视图是DuplicateParentStateEnabled,则该方法会将子视图的边界设置为触摸事件的坐标,然后调用子视图的dispatchTouchEvent方法。
总结
通过对dispatchTouchEvent方法的分析,我们了解了Android ViewGroup的事件分发机制。该机制主要通过循环遍历子视图,并调用子视图的dispatchTouchEvent方法来实现。如果子视图处理了触摸事件,则该方法返回true,否则返回false。
希望本文对您理解Android ViewGroup的事件分发机制有所帮助。如果您有任何问题或建议,欢迎随时与我联系。