ViewGroup的dispatchTouchEvent相关源码
boolean handled = false;
...
if (actionMasked == MotionEvent.ACTION_DOWN) {
//清除所有的触摸链touch targets,mFirstTouchTarget为null
//重置touch状态标识,所以说明requestDisallowInterceptTouchEvent方法对于DOWN事件是无效的
cancelAndClearTouchTargets(ev);
resetTouchState();
}
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
//检查是否需要拦截事件
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action);
} else {
intercepted = false;
}
} else {
//不是DOWN事件并且mFirstTouchTarget为null,说明拦截Touch事件
intercepted = true;
}
mFirstTouchTarget不为null表示没有拦截了事件并且子View消费了该事件。
mFirstTouchTarget为null表示拦截了事件或者没有拦截但是子View没有消费该事件。
boolean alreadyDispatchedToNewTouchTarget = false;
if (!canceled && !intercepted) {
....
if (actionMasked == MotionEvent.ACTION_DOWN
|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
...
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
...
//方法内把消费了事件的View添加到了touch targets中,
//即mFirstTouchTarget此时不为null。可知,如果dispatchTransformedTouchEvent为false(不消费),
//那么 mFirstTouchTarget就为null
newTouchTarget = addTouchTarget(child, idBitsToAssign);
//事件被消费,设置为true,下面判断会使用到
alreadyDispatchedToNewTouchTarget = true;
break;
}
...
}
...
}
if (newTouchTarget == null && mFirstTouchTarget != null) {
newTouchTarget = mFirstTouchTarget;
while (newTouchTarget.next != null) {
newTouchTarget = newTouchTarget.next;
}
newTouchTarget.pointerIdBits |= idBitsToAssign;
}
}
}
//事件分发给子View
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
...
if (child == null) {
//直接到View的dispatchTouchEvent处理事件
handled = super.dispatchTouchEvent(event);
} else {
...
handled = child.dispatchTouchEvent(event);
}
}
if (mFirstTouchTarget == null) {
//此时事件被拦截了或者事件没有子View消费,自己处理事件
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
TouchTarget predecessor = null;
TouchTarget target = mFirstTouchTarget;
while (target != null) {
final TouchTarget next = target.next;
//只有DOWN事件被消费了alreadyDispatchedToNewTouchTarget设置为true才会到这里
//不处理直接返回true
if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
handled = true;
} else {
//处理除了DOWN事件以外的事件分发
final boolean cancelChild = resetCancelNextUpFlag(target.child)
|| intercepted;
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
//mFirstTouchTarget最终会变为null
if (cancelChild) {
if (predecessor == null) {
mFirstTouchTarget = next;
} else {
predecessor.next = next;
}
target.recycle();
target = next;
continue;
}
}
predecessor = target;
target = next;
}
}
测试
布局为ViewGroupA里面添加ViewGroupB里面添加View
View的clickable设置为true。
E/Test-Activity: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_DOWN
E/Test-View: dispatchTouchEvent:ACTION_DOWN
E/Test-View: onTouchEvent:ACTION_DOWN
E/Test-Activity: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_MOVE
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_MOVE
E/Test-View: dispatchTouchEvent:ACTION_MOVE
E/Test-View: onTouchEvent:ACTION_MOVE
E/Test-Activity: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_UP
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_UP
E/Test-View: dispatchTouchEvent:ACTION_UP
E/Test-View: onTouchEvent:ACTION_UP
只要子View是可点击的就会消费事件,所以子View消费DOWN事件,两个ViewGroup的mFirstTouchTarget都不为null,所以此时的MOVE和UP事件正常经过dispatchTouchEvent和onInterceptTouchEvent,通过dispatchTransformedTouchEvent分发到View处理事件。
View不设置clickable
E/Test-Activity: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_DOWN
E/Test-View: dispatchTouchEvent:ACTION_DOWN
E/Test-View: onTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: onTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: onTouchEvent:ACTION_DOWN
E/Test-Activity: onTouchEvent:ACTION_DOWN
E/Test-Activity: dispatchTouchEvent:ACTION_MOVE
E/Test-Activity: onTouchEvent:ACTION_MOVE
E/Test-Activity: dispatchTouchEvent:ACTION_UP
E/Test-Activity: onTouchEvent:ACTION_UP
DOWN事件分发到View,但是没有View去消费该事件,则View的onTouchEvent返回false,B的mFirstTouchTarget为null,B自身处理事件onTouchEvent返回false,A同样处理返回false一直到Activity,getWindow().superDispatchTouchEvent(ev)返回false,调用自己的onTouchEvent处理事件。由于现在的mFirstTouchTarget都为null,所以MOVE和UP事件不会被分发到子View处理。
View的clickable设置为true,B的dispatchTouchEvent的Down事件return true
E/Test-Activity: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_DOWN
E/Test-Activity: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_MOVE
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—B: onTouchEvent:ACTION_MOVE
E/Test-Activity: onTouchEvent:ACTION_MOVE
E/Test-Activity: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_UP
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—B: onTouchEvent:ACTION_UP
E/Test-Activity: onTouchEvent:ACTION_UP
A正常分发到B,但是B的DOWN事件直接返回了true,所以B的mFirstTouchTarget为null,A的mFirstTouchTarget不为null,此时alreadyDispatchedToNewTouchTarget为true,DOWN事件不会继续分发下去直接设置handled为true,那么Activity由于getWindow().superDispatchTouchEven为true也不会调用onTouchEvent。MOVE和UP事件到来的时候,由于B的mFirstTouchTarget为null,在开始判断里面不会走onInterceptTouchEvent而是直接设置intercept为true,然后走自身的onTouchEvent方法返回false。A的mFirstTouchTarget不为null,dispatchTransformedTouchEvent为false,handled默认为false,所以到Activity的时候,会调用onTouchEvent。
B的onInterceptTouchEvent的DONW事件return true
E/Test-Activity: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: onTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: onTouchEvent:ACTION_DOWN
E/Test-Activity: onTouchEvent:ACTION_DOWN
E/Test-Activity: dispatchTouchEvent:ACTION_MOVE
E/Test-Activity: onTouchEvent:ACTION_MOVE
E/Test-Activity: dispatchTouchEvent:ACTION_UP
E/Test-Activity: onTouchEvent:ACTION_UP
DOWN事件在B中被拦截了,intercept为true,该事件将不会分到到子View,所以B的mFirstTouchTarget为null,调用自己的onTouchEvent返回false,所以A中dispatchTransformedTouchEvent返回为false,此时的mFirstTouchTarget也为null,调用自己的onTouchEvent返回false,Activity调用onTouchEvent。由于此时所有的mFirstTouchTarget都为null,所以MOVE和UP事件都只会在Activity中处理。
B的onInterceptTouchEvent的MOVE事件return true
E/Test-Activity: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_DOWN
E/Test-View: dispatchTouchEvent:ACTION_DOWN
E/Test-View: onTouchEvent:ACTION_DOWN
E/Test-Activity: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_UP
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_UP
E/Test-View: dispatchTouchEvent:ACTION_UP
E/Test-View: onTouchEvent:ACTION_UP
此时没有MOVE事件,DOWN和UP事件正常分发到View上面消费。
E/Test-Activity: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_DOWN
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_DOWN
E/Test-View: dispatchTouchEvent:ACTION_DOWN
E/Test-View: onTouchEvent:ACTION_DOWN
E/Test-Activity: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_MOVE
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—B: onInterceptTouchEvent:ACTION_MOVE
E/Test-Activity: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_MOVE
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_MOVE
E/Test-ViewGroup—B: onTouchEvent:ACTION_MOVE
E/Test-Activity: onTouchEvent:ACTION_MOVE
E/Test-Activity: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—A: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—A: onInterceptTouchEvent:ACTION_UP
E/Test-ViewGroup—B: dispatchTouchEvent:ACTION_UP
E/Test-ViewGroup—B: onTouchEvent:ACTION_UP
E/Test-Activity: onTouchEvent:ACTION_UP
DOWN事件的时候,A和B的mFirstTouchTarget都不为null,MOVE事件到来的时候,此时intercept为true,则cancelChild为true,B的mFirstTouchTarget会变为null,在接下来的MOVE事件到来的时候,会调用自己的onTouchEvent返回false到A默认handled默认返回false,Activity调用onTouchEvent。