将分为三部分博客来记录android事件传递机制
1.首先我先分析一下android中的控件的结构,
activity作为一个活动中包含一个window窗口,window下可以放多个ViewGroup,viewGroup中可以放多个view
2.但是我们通过源码可以看出ViewGroup也是继承View的
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
3.那我就从view开始看起,通过看源码可以发现view中包含两个处理时间的方法,
dispatchTouchEvent(MotionEvent event) 和onTouchEvent(MotionEvent event)
4.我们知道事件传递机制都是先调用dispatchTouchEvent()方法,所有我们看一下源码
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.isTargetAccessibilityFocus()) {
if (!isAccessibilityFocusedViewOrHost()) {
return false;
}
event.setTargetAccessibilityFocus(false);
}
boolean result = false;
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
stopNestedScroll();
}
if (onFilterTouchEventForSecurity(event)) {
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);
}
if (actionMasked == MotionEvent.ACTION_UP ||
actionMasked == MotionEvent.ACTION_CANCEL ||
(actionMasked == MotionEvent.ACTION_DOWN && !result)) {
stopNestedScroll();
}
return result;
}
前几行是关于判读view是否有焦点的代码我们不用看,主要看其中这段代码
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
从这段代码中可以看的出来view是先判读用户是否绑定了OnTouchListener,如果绑定了则调用用户定义的onTouch方法,并且把返回值作为最终结果返回。如果没有定义就调用view中的onTouchEvent方法并返回结果。(在onTouch方法中会调用点击事件处理)
5.看过view的代码你应该知道了view中dispatchTouchEvent()和onTouchEvent()的关系了吧,是前者调用了后者。
6.接下来我们看一下ViewGroup中的代码,这个要比view要复杂一些,通过看源码我们可以看出来ViewGroup继承View并且重写了dispatchTouchEvent();和增加了OnInterceptTouchEvent();
7.还是首先我们看一下dispatchTouchEvent()中的代码
由于该方法的代码过长我就不粘贴了,大家可以看自己的android源码,在第1929行就是该方法,这个方法先是在1960行调用了onInterceptTouchEvent方法,并记录返回值intercepted ,如果intercepted==flase那么将调用ViewGroup中的所有子View的dispatchTouchEvent()。一但有某一个view的方法返回true则ViewGroup的dispatchTouch()返回true。
8.从这一点我们就能知道了onInterceptTouchEvent是怎么进行屏蔽的了,onInterceptTouchEvent返回为true时则不会调用子view的dispatchTouch,只调用viewGroup的super.onTouchEvent()。
9.那么什么时候viewGroup的子view的dispatchTouch()会返回true?刚才我们在看view的代码的时候知道,当view中的onTouchEvent返回true时分发函数也会返回true。
10.从这些代码中我们就能理解了,时间是如何向下传递的了。那么如果没有子view呢?在2372行代码中我们能知道,如果没有子view则ViewGroup调用super.dispatchTouch()
注:viewGroup中的onInterceptTouchEvent默认返回的是false,也就是默认是都要给子view进行事件传递的,但是有些继承了viewGroup并且重写了该方法的就要具体问题具体分析了。
下一期我讲述事件传递到最低端后是否会回传给上层控件
网友评论