ViewGroup的事件分发伪代码
public boolean dispatchTouchEvent(MotionEvent ev) {
/*
ACTION_DOWNA事件初始化
由于一个完整的事件序列是以DOWN开始,以UP结束,
所以如果是DOWN事件,那么说明是一个新的事件序列,所以需要初始化之前的状态。
*/
if (action == ACTIONN_DOWN) {
mFrstTouchTarge = null;
FLAG_DISALLOW_INTERCEPT=false;
}
// 检查是否拦截
boolean intercepted;
if (action == ACTIONN_DOWN || mFrstTouchTarge != null) {
// FLAG_DISALLOW_INTERCEPT一般通过子View的requestDisallowInterceptTouchEvent来设置。
if (!FLAG_DISALLOW_INTERCEPT) {
//当ViewGroup要拦截事件的时候,那么后续的事件序列都将交给它处理,而不用再调用onInterceptTouchEvent()方法了,所以该方法并不是每次事件都会调用的。
intercepted = onInterceptTouchEvent(event);
}else {
intercepted=true;
}
}else{
intercepted = true;
}
TouchTarget newTouchTarget = null; // 1
boolean alreadyDispatchedToNewTouchTarget = false;
if (!canceled && !intercepted) {
if (actionMasked == MotionEvent.ACTION_DOWN
|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
// ACTION_DOWN时
final int childrenCount = mChildrenCount;
if (newTouchTarget == null && childrenCount != 0) {
// 有子View
final View[] children = mChildren;
for (int i = childrenCount - 1; i >= 0; i--) {
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
// 是否在执行动画以及是否在该Veiw的点击区域内,否则continue
continue;
}
// 到这里说明找到了子View
newTouchTarget = getTouchTarget(child);
//把事件分发给子View
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
newTouchTarget = addTouchTarget(child, idBitsToAssign);
// 如果分发给子View的分发返回的true,说明子View消耗掉了事件,alreadyDispatchedToNewTouchTarget设为true
alreadyDispatchedToNewTouchTarget = true;
break;
}
}
}
}
}
// 继续执行到这里
if (mFirstTouchTarget == null) {
// 如果没有找到子View,调用dispatchTransformedTouchEvent方法,第三个参数是null,则调用super的分发方法,也就是viewgroup自己消费
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
// 如果找到子View
TouchTarget target = mFirstTouchTarget;
while (target != null) {
if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
// 子Veiw消耗掉了事件,则直接返回true。一定是Down,其他事件是不会进入上面的条件的。
handled = true;
} else {
// 其他事件或者Down事件没有消耗,继续调用子View分发
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
}
}
}
}
// 调子View分发的方法
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
final boolean handled;
if (child == null) {
// 没有子View,调super,也就是View的分发方法(View 的分发方法和viewgroup的不同,没有拦截方法,会调用onTouchEvent方法)
handled = super.dispatchTouchEvent(event);
} else {
// 有子View,调子View的分发方法,不管子View是View还是ViewGroup
handled = child.dispatchTouchEvent(event);
}
return handled;
}
// 给mFirstTouchTarget赋值,他影响拦截方法
private TouchTarget addTouchTarget(View child, int pointerIdBits) {
TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
target.next = mFirstTouchTarget;
mFirstTouchTarget = target;
return target;
}
// 拦截的方法,默认返回false,我们可以重写该方法
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}