@Override publicbooleandispatchTouchEvent(MotionEvent ev) { if (mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onTouchEvent(ev, 1); } // If the event targets the accessibility focused view and this is it, start // normal event dispatch. Maybe a descendant is what will handle the click. if (ev.isTargetAccessibilityFocus() && isAccessibilityFocusedViewOrHost()) { ev.setTargetAccessibilityFocus(false); } // 返回值,代表着该View是否处理事件 booleanhandled=false; // 判断当前 window 是否有被遮挡,若返回 false 则丢弃这个事件 if (onFilterTouchEventForSecurity(ev)) { finalintaction= ev.getAction(); finalintactionMasked= action & MotionEvent.ACTION_MASK;
// 如果是 ACTION_DOWN 事件,那么需要恢复初始状态以及 mFirstTouchTarget 置空等 if (actionMasked == MotionEvent.ACTION_DOWN) { // Throw away all previous state when starting a new touch gesture. // The framework may have dropped the up or cancel event for the previous gesture // due to an app switch, ANR, or some other state change. cancelAndClearTouchTargets(ev); // 在 resetTouchState 会对 FLAG_DISALLOW_INTERCEPT 重置 resetTouchState(); }
// ----------第 2 小点---------- // disallowIntercept 代表着子View是否禁止让父ViewGroup拦截事件 finalbooleandisallowIntercept= (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; // 如果不禁止,就调用 onInterceptTouchEvent 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.
// 获取 z 轴上从大到小排序的子 view 顺序 final ArrayList<View> preorderedList = buildTouchDispatchChildList(); finalbooleancustomOrder= preorderedList == null && isChildrenDrawingOrderEnabled(); final View[] children = mChildren; // 开始遍历子 view for (inti= childrenCount - 1; i >= 0; i--) { // 确认子 View 的下标 finalintchildIndex= getAndVerifyPreorderedIndex( childrenCount, i, customOrder); // 根据下标,得到子View finalViewchild= getAndVerifyPreorderedView( preorderedList, children, childIndex);
// 如果当前 view 没有焦点,那么跳过 if (childWithAccessibilityFocus != null) { if (childWithAccessibilityFocus != child) { continue; } childWithAccessibilityFocus = null; i = childrenCount - 1; } // 点击是否落在子view范围内和子view是否正在动画 if (!canViewReceivePointerEvents(child) || !isTransformedTouchPointInView(x, y, child, null)) { ev.setTargetAccessibilityFocus(false); continue; }
newTouchTarget = getTouchTarget(child); if (newTouchTarget != null) { // Child is already receiving touch within its bounds. // Give it the new pointer in addition to the ones it is handling. newTouchTarget.pointerIdBits |= idBitsToAssign; break; }
resetCancelNextUpFlag(child); // 分发给该子 View 的 dispatchTouchEvent 方法 if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) { // Child wants to receive touch within its bounds. mLastTouchDownTime = ev.getDownTime(); if (preorderedList != null) { // childIndex points into presorted list, find original index for (intj=0; j < childrenCount; j++) { if (children[childIndex] == mChildren[j]) { mLastTouchDownIndex = j; break; } } } else { mLastTouchDownIndex = childIndex; } mLastTouchDownX = ev.getX(); mLastTouchDownY = ev.getY(); //给 mFirstTouchTarget 赋值,该事件已经交给子 View 处理了 newTouchTarget = addTouchTarget(child, idBitsToAssign); alreadyDispatchedToNewTouchTarget = true; break; }
// The accessibility focus didn't handle the event, so clear // the flag and do a normal dispatch to all children. ev.setTargetAccessibilityFocus(false); } if (preorderedList != null) preorderedList.clear(); }
if (newTouchTarget == null && mFirstTouchTarget != null) { // Did not find a child to receive the event. // Assign the pointer to the least recently added target. newTouchTarget = mFirstTouchTarget; while (newTouchTarget.next != null) { newTouchTarget = newTouchTarget.next; } newTouchTarget.pointerIdBits |= idBitsToAssign; } } }