分享

细说Android事件传递机制(dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent)

 QCamera 2015-06-03
001.public boolean dispatchTouchEvent(MotionEvent ev) {
002.    if (mInputEventConsistencyVerifier != null) {
003.        mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
004.    }
005. 
006.    boolean handled = false;
007.    if (onFilterTouchEventForSecurity(ev)) {
008.        final int action = ev.getAction();
009.        final int actionMasked = action & MotionEvent.ACTION_MASK;
010. 
011.        // Handle an initial down.
012.        if (actionMasked == MotionEvent.ACTION_DOWN) {
013.            // Throw away all previous state when starting a new touch gesture.
014.            // The framework may have dropped the up or cancel event for the previous gesture
015.            // due to an app switch, ANR, or some other state change.
016.            cancelAndClearTouchTargets(ev);
017.            resetTouchState();
018.        }
019. 
020.        // Check for interception.
021.        final boolean intercepted;
022.        if (actionMasked == MotionEvent.ACTION_DOWN
023.                || mFirstTouchTarget != null) {
024.            final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
025.            if (!disallowIntercept) {
026.                <strong>intercepted = onInterceptTouchEvent(ev);</strong>
027.                ev.setAction(action); // restore action in case it was changed
028.            } else {
029.                intercepted = false;
030.            }
031.        } else {
032.            // There are no touch targets and this action is not an initial down
033.            // so this view group continues to intercept touches.
034.            intercepted = true;
035.        }
036. 
037.        // Check for cancelation.
038.        final boolean canceled = resetCancelNextUpFlag(this)
039.                || actionMasked == MotionEvent.ACTION_CANCEL;
040. 
041.        // Update list of touch targets for pointer down, if needed.
042.        final boolean split = (mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) != 0;
043.        TouchTarget newTouchTarget = null;
044.        boolean alreadyDispatchedToNewTouchTarget = false;
045.        <strong>if (!canceled && !intercepted)</strong> {
046.            if (actionMasked == MotionEvent.ACTION_DOWN
047.                    || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
048.                    || actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
049.                final int actionIndex = ev.getActionIndex(); // always 0 for down
050.                final int idBitsToAssign = split ? 1 << ev.getPointerId(actionIndex)
051.                        : TouchTarget.ALL_POINTER_IDS;
052. 
053.                // Clean up earlier touch targets for this pointer id in case they
054.                // have become out of sync.
055.                removePointersFromTouchTargets(idBitsToAssign);
056. 
057.                final int childrenCount = mChildrenCount;
058.                if (childrenCount != 0) {
059.                    // Find a child that can receive the event.
060.                    // Scan children from front to back.
061.                    final View[] children = mChildren;
062.                    final float x = ev.getX(actionIndex);
063.                    final float y = ev.getY(actionIndex);
064. 
065.                    final boolean customOrder = isChildrenDrawingOrderEnabled();
066.                    for (int i = childrenCount - 1; i >= 0; i--) {
067.                        final int childIndex = customOrder ?
068.                                getChildDrawingOrder(childrenCount, i) : i;
069.                        final View child = children[childIndex];
070.                        if (!canViewReceivePointerEvents(child)
071.                                || !isTransformedTouchPointInView(x, y, child, null)) {
072.                            continue;
073.                        }
074. 
075.                        newTouchTarget = getTouchTarget(child);
076.                        if (newTouchTarget != null) {
077.                            // Child is already receiving touch within its bounds.
078.                            // Give it the new pointer in addition to the ones it is handling.
079.                            newTouchTarget.pointerIdBits |= idBitsToAssign;
080.                            break;
081.                        }
082. 
083.                        resetCancelNextUpFlag(child);
084.                        if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
085.                            // Child wants to receive touch within its bounds.
086.                            mLastTouchDownTime = ev.getDownTime();
087.                            mLastTouchDownIndex = childIndex;
088.                            mLastTouchDownX = ev.getX();
089.                            mLastTouchDownY = ev.getY();
090.                            newTouchTarget = addTouchTarget(child, idBitsToAssign);
091.                            alreadyDispatchedToNewTouchTarget = true;
092.                            break;
093.                        }
094.                    }
095.                }
096. 
097.                if (newTouchTarget == null && mFirstTouchTarget != null) {
098.                    // Did not find a child to receive the event.
099.                    // Assign the pointer to the least recently added target.
100.                    newTouchTarget = mFirstTouchTarget;
101.                    while (newTouchTarget.next != null) {
102.                        newTouchTarget = newTouchTarget.next;
103.                    }
104.                    newTouchTarget.pointerIdBits |= idBitsToAssign;
105.                }
106.            }
107.        }
108. 
109.        // Dispatch to touch targets.
110.        if (mFirstTouchTarget == null) {
111.            // No touch targets so treat this as an ordinary view.
112.            handled = dispatchTransformedTouchEvent(ev, canceled, null,
113.                    TouchTarget.ALL_POINTER_IDS);
114.        } else {
115.            // Dispatch to touch targets, excluding the new touch target if we already
116.            // dispatched to it.  Cancel touch targets if necessary.
117.            TouchTarget predecessor = null;
118.            TouchTarget target = mFirstTouchTarget;
119.            while (target != null) {
120.                final TouchTarget next = target.next;
121.                if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
122.                    handled = true;
123.                } else {
124.                    final boolean cancelChild = resetCancelNextUpFlag(target.child)
125.                    || intercepted;
126.                    if (dispatchTransformedTouchEvent(ev, cancelChild,
127.                            target.child, target.pointerIdBits)) {
128.                        handled = true;
129.                    }
130.                    if (cancelChild) {
131.                        if (predecessor == null) {
132.                            mFirstTouchTarget = next;
133.                        } else {
134.                            predecessor.next = next;
135.                        }
136.                        target.recycle();
137.                        target = next;
138.                        continue;
139.                    }
140.                }
141.                predecessor = target;
142.                target = next;
143.            }
144.        }
145. 
146.        // Update list of touch targets for pointer up or cancel, if needed.
147.        if (canceled
148.                || actionMasked == MotionEvent.ACTION_UP
149.                || actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
150.            resetTouchState();
151.        } else if (split && actionMasked == MotionEvent.ACTION_POINTER_UP) {
152.            final int actionIndex = ev.getActionIndex();
153.            final int idBitsToRemove = 1 << ev.getPointerId(actionIndex);
154.            removePointersFromTouchTargets(idBitsToRemove);
155.        }
156.    }
157. 
158.    if (!handled && mInputEventConsistencyVerifier != null) {
159.        mInputEventConsistencyVerifier.onUnhandledEvent(ev, 1);
160.    }
161.    return handled;
162.}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多