Fix new back arrow's "over eager" appearance There are two fixes in this cl: 1. The back arrow launches into its ENTRY state too easily: guard it with a minimum motion threshold. 2. The cancel animation is triggered upon MotionEvent.ACITON_UP, even when there has not been sufficient motion to trigger a change from GONE -> ENTRY (invisible to appearance): prevent GONE -> CANCELLED state transitions. Bug: 238907408 Test: manual Change-Id: I5ab8042fc675cfc527b837578b1d415d2d061d79
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt index a833670..28ab83c 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -30,6 +30,7 @@ import android.view.MotionEvent import android.view.VelocityTracker import android.view.View +import android.view.ViewConfiguration import android.view.WindowManager import android.view.animation.DecelerateInterpolator import android.view.animation.PathInterpolator @@ -98,6 +99,7 @@ context: Context, private var backAnimation: BackAnimation?, private val windowManager: WindowManager, + private val viewConfiguration: ViewConfiguration, @Main private val mainHandler: Handler, private val vibratorHelper: VibratorHelper, private val configurationController: ConfigurationController, @@ -112,6 +114,7 @@ */ class Factory @Inject constructor( private val windowManager: WindowManager, + private val viewConfiguration: ViewConfiguration, @Main private val mainHandler: Handler, private val vibratorHelper: VibratorHelper, private val configurationController: ConfigurationController, @@ -123,6 +126,7 @@ context, backAnimation, windowManager, + viewConfiguration, mainHandler, vibratorHelper, configurationController, @@ -164,6 +168,10 @@ private var gestureStartTime = 0L + // Whether the current gesture has moved a sufficiently large amount, + // so that we can unambiguously start showing the ENTRY animation + private var hasPassedDragSlop = false + private val failsafeRunnable = Runnable { onFailsafe() } private enum class GestureState { @@ -304,18 +312,17 @@ startX = event.x startY = event.y gestureStartTime = SystemClock.uptimeMillis() - - // Reset the arrow to the side - updateArrowState(GestureState.ENTRY) - - windowManager.updateViewLayout(mView, layoutParams) - mView.startTrackingShowBackArrowLatency() } - MotionEvent.ACTION_MOVE -> handleMoveEvent(event) + MotionEvent.ACTION_MOVE -> { + // only go to the ENTRY state after some minimum motion has occurred + if (dragSlopExceeded(event.x, startX)) { + handleMoveEvent(event) + } + } MotionEvent.ACTION_UP -> { if (currentState == GestureState.ACTIVE) { updateArrowState(if (isFlung()) GestureState.FLUNG else GestureState.COMMITTED) - } else { + } else if (currentState != GestureState.GONE) { // if invisible, skip animation updateArrowState(GestureState.CANCELLED) } velocityTracker = null @@ -330,6 +337,28 @@ } } + /** + * Returns false until the current gesture exceeds the touch slop threshold, + * and returns true thereafter (we reset on the subsequent back gesture). + * The moment it switches from false -> true is important, + * because that's when we switch state, from GONE -> ENTRY. + * @return whether the current gesture has moved past a minimum threshold. + */ + private fun dragSlopExceeded(curX: Float, startX: Float): Boolean { + if (hasPassedDragSlop) return true + + if (abs(curX - startX) > viewConfiguration.scaledTouchSlop) { + // Reset the arrow to the side + updateArrowState(GestureState.ENTRY) + + windowManager.updateViewLayout(mView, layoutParams) + mView.startTrackingShowBackArrowLatency() + + hasPassedDragSlop = true + } + return hasPassedDragSlop + } + private fun updateArrowStateOnMove(yTranslation: Float, xTranslation: Float) { if (!currentState.isInteractive()) return @@ -533,6 +562,7 @@ } private fun resetOnDown() { + hasPassedDragSlop = false hasHapticPlayed = false totalTouchDelta = 0f vibrationTime = 0