一、父View拦截事件后,会向子View发送一个MotionEvent.ACTION_CANCEL
-
父View拦截事件后,会将intercepted设置为true -
事件被拦截后,mFirstTouchTarget此时的值为子View,还不是null -
将该事件设置为MotionEvent.ACTION_CANCEL,将该事件分发到子View中 -
子view会返回true消耗掉该事件
if (actionMasked == MotionEvent.ACTION_DOWN|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
//事件被拦截之后,intercepted = true
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action);
} else {
intercepted = false;
}
} else {
intercepted = true;
}
//事件被拦截之后,mFirstTouchTarget此时的值为子View,还不是null,直接走到else中.
if (mFirstTouchTarget == null) {
...
} else {
...
//因为 intercepted = true, 所以cancelChild为true.看看dispatchTransformedTouchEvent方法中,如果cancelChild为true时候会做什么.
final boolean cancelChild = resetCancelNextUpFlag(target.child)|| intercepted;
if (dispatchTransformedTouchEvent(ev, cancelChild,target.child, target.pointerIdBits)) {
handled = true;
}
...
}
//看看cancel 为true时候会做什么.
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
final boolean handled;
final int oldAction = event.getAction();
//cancel为true
if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {
//会将该事件设置为MotionEvent.ACTION_CANCEL
event.setAction(MotionEvent.ACTION_CANCEL);
if (child == null) {
//再将该事件分发到子View中, 子View就会收到MotionEvent.ACTION_CANCEL事件
handled = super.dispatchTouchEvent(event);
} else {
handled = child.dispatchTouchEvent(event);
}
event.setAction(oldAction);
//子View会返回true,消耗掉该事件.
return handled;
}
}
事件如何分发到ViewGroup中
//在ViewGroup中,dispatchTouchEvent方法中最后执行的几行代码会将mFirstTouchTarget置为null
//如此,当非Down事件进来之后会直分发到ViewGroup中.
public boolean dispatchTouchEvent(MotionEvent ev) {
...
//若mFirstTouchTarget等于null,会执行dispatchTransformedTouchEvent方法,参数View 为null.
//这样事件就被分发到
if (mFirstTouchTarget == null) {
handled = dispatchTransformedTouchEvent(ev, canceled, null,TouchTarget.ALL_POINTER_IDS);
} else {
TouchTarget predecessor = null;
TouchTarget target = mFirstTouchTarget;
final TouchTarget next = target.next;
// 这里就表示为Down以外的事件分发流程了.
// intercepted表示ViewGroup是否拦截该次事件.
// 拦截时intercepted=true则cancelChild=true,不拦截时intercepted=false则cancelChild=false.
final boolean cancelChild = resetCancelNextUpFlag(target.child) || intercepted;
// 这里是将事件分发到目标子View中,dispatchTransformedTouchEvent()下面分析.
if (dispatchTransformedTouchEvent(ev, cancelChild,target.child, target.pointerIdBits)) {
// 如果目标子View消耗了该事件,ViewGroup.dispatchTouchEvent()就返回true.
handled = true;
}
// 如果ViewGruop拦截事件,则cancelChild=true.
if (cancelChild) {
// 这句话意思是mFirstTouchTarget将被他的上一个TouchTarget取代.TouchTarget是一个链表结构.
// mFirstTouchTarget对象中的当前目标子View对象,今后将不会在接收到当前的事件序列中的任何事件了.
// 假如当前mFirstTouchTarget上一个TouchTarget对象为null,那么mFirstTouchTarget也将为null,那么当该事件序列中的下一个事件到来时,ViewGroup将会把该事件交由自己处理.
mFirstTouchTarget = next;
}
}
|