dispatchTouchEvent 方法可以根据DOWN事件和move,up事件分别分析。本文章不考虑多触摸点,TouchTarget链是储存了多触摸点,pointerIdBits 属性表示触摸点Id
1.DOWN事件,主要作用是确定消费路线(把处理事件的View赋值给mFirstTouchTarget)
dispatchTouchEvent方法的简要代码
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); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
if (!canceled && !intercepted){
//Down事件
if (actionMasked == MotionEvent.ACTION_DOWN
|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE){
if(子view消费事件){
mFirstTouchTarget=子view;
}
}
}
// move,up事件
if (mFirstTouchTarget == null) {
// No touch targets so treat this as an ordinary view.
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)
}
具体过程:遍历子view ,判断触摸点是否在该view中,不在,跳过该view
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
ev.setTargetAccessibilityFocus(false);
continue;
}
触摸点在该view的范围中,调用dispatchTransformedTouchEvent, 把坐标系转换为子view 坐标系,事件传递给子view,子view执行onTouchEvent 返回值
// Perform any necessary transformations and dispatch.
if (child == null) {
handled = super.dispatchTouchEvent(transformedEvent);
} else {
final float offsetX = mScrollX - child.mLeft;
final float offsetY = mScrollY - child.mTop;
transformedEvent.offsetLocation(offsetX, offsetY);
if (! child.hasIdentityMatrix()) {
transformedEvent.transform(child.getInverseMatrix());
}
handled = child.dispatchTouchEvent(transformedEvent);
}
当返回值为true时,表示子view消费了这个点击事件,把该View赋值给mFirstTouchTarget,表示ViewGroup中有子View消费了这个点击事件。
mFirstTouchTarget = target;
alreadyDispatchedToNewTouchTarget = true;
结论:在View树中每个ViewGroup的mFirstTouchTarget属性指向下个消费了事件的子view,形成一个消费链。这是Down事件的主要功能。
2.move,up事件
遍历完子view后,mFirstTouchTarget为空直接调用自身的onTouchEvent方法,不为空表示有子view消费事件,事件向下传递。