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. }
|