diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index bfd76c5e29f9f..9b45bea1974c2 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -44,7 +44,7 @@ 16dp - 400dp + 412dp 64dp @@ -80,13 +80,11 @@ 8dp 9dp - - 412dp 18dp 74dp 60dp - 30dp - 30dp + 30dp + 30dp 7dp 10dp diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt index 56ad19ae89ca6..2822435639524 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt @@ -58,14 +58,16 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : SpringForce().apply { stiffness = 600f dampingRatio = 0.65f - }) + } + ) private val backgroundHeight = AnimatedFloat( name = "backgroundHeight", SpringForce().apply { stiffness = 600f dampingRatio = 0.65f - }) + } + ) /** * Corners of the background closer to the edge of the screen (where the arrow appeared from). @@ -76,18 +78,20 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : SpringForce().apply { stiffness = 400f dampingRatio = SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY - }) + } + ) /** * Corners of the background further from the edge of the screens (toward the direction the * arrow is being dragged). Used for animating [arrowBackgroundRect] */ - private val backgroundDragCornerRadius = AnimatedFloat( + private val backgroundFarCornerRadius = AnimatedFloat( name = "backgroundDragCornerRadius", SpringForce().apply { stiffness = 2200f dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY - }) + } + ) /** * Left/right position of the background relative to the canvas. Also corresponds with the @@ -96,14 +100,32 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : */ private var horizontalTranslation = AnimatedFloat("horizontalTranslation", SpringForce()) + private val currentAlpha: FloatPropertyCompat = + object : FloatPropertyCompat("currentAlpha") { + override fun setValue(panel: BackPanel, value: Float) { + panel.alpha = value + } + + override fun getValue(panel: BackPanel): Float = panel.alpha + } + + private val alphaAnimation = SpringAnimation(this, currentAlpha) + .setSpring( + SpringForce() + .setStiffness(60f) + .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY) + ) + /** * Canvas vertical translation. How far up/down the arrow and background appear relative to the * canvas. */ - private var verticalTranslation: AnimatedFloat = - AnimatedFloat("verticalTranslation", SpringForce().apply { + private var verticalTranslation: AnimatedFloat = AnimatedFloat( + name = "verticalTranslation", + SpringForce().apply { stiffness = SpringForce.STIFFNESS_MEDIUM - }) + } + ) /** * Use for drawing debug info. Can only be set if [DEBUG]=true @@ -160,6 +182,17 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : animation.animateToFinalPosition(restingPosition + stretchAmount) } + /** + * Animates to a new position ([finalPosition]) that is the given fraction ([amount]) + * between the existing [restingPosition] and the new [finalPosition]. + * + * The [restingPosition] will remain unchanged. Only the animation is updated. + */ + fun stretchBy(finalPosition: Float, amount: Float) { + val stretchedAmount = amount * (finalPosition - restingPosition) + animation.animateToFinalPosition(restingPosition + stretchedAmount) + } + fun updateRestingPosition(pos: Float, animated: Boolean) { restingPosition = pos if (animated) @@ -192,7 +225,10 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : } fun addEndListener(endListener: DelayedOnAnimationEndListener): Boolean { - return if (horizontalTranslation.animation.isRunning) { + return if (alphaAnimation.isRunning) { + alphaAnimation.addEndListener(endListener) + true + } else if (horizontalTranslation.animation.isRunning) { horizontalTranslation.animation.addEndListener(endListener) true } else { @@ -202,47 +238,59 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : } fun setStretch( - arrowLengthStretch: Float, - arrowHeightStretch: Float, - backgroundWidthStretch: Float, - backgroundHeightStretch: Float, - backgroundEdgeCornerRadiusStretch: Float, - backgroundDragCornerRadiusStretch: Float, - horizontalTranslationStretch: Float + horizontalTranslationStretchAmount: Float, + arrowStretchAmount: Float, + backgroundWidthStretchAmount: Float, + fullyStretchedDimens: EdgePanelParams.BackIndicatorDimens ) { - arrowLength.stretchTo(arrowLengthStretch) - arrowHeight.stretchTo(arrowHeightStretch) - backgroundWidth.stretchTo(backgroundWidthStretch) - backgroundHeight.stretchTo(backgroundHeightStretch) - backgroundEdgeCornerRadius.stretchTo(backgroundEdgeCornerRadiusStretch) - backgroundDragCornerRadius.stretchTo(backgroundDragCornerRadiusStretch) - horizontalTranslation.stretchTo(horizontalTranslationStretch) + horizontalTranslation.stretchBy( + finalPosition = fullyStretchedDimens.horizontalTranslation, + amount = horizontalTranslationStretchAmount + ) + arrowLength.stretchBy( + finalPosition = fullyStretchedDimens.arrowDimens.length, + amount = arrowStretchAmount + ) + arrowHeight.stretchBy( + finalPosition = fullyStretchedDimens.arrowDimens.height, + amount = arrowStretchAmount + ) + backgroundWidth.stretchBy( + finalPosition = fullyStretchedDimens.backgroundDimens.width, + amount = backgroundWidthStretchAmount + ) } fun resetStretch() { - setStretch(0f, 0f, 0f, 0f, 0f, 0f, 0f) + horizontalTranslation.stretchTo(0f) + arrowLength.stretchTo(0f) + arrowHeight.stretchTo(0f) + backgroundWidth.stretchTo(0f) + backgroundHeight.stretchTo(0f) + backgroundEdgeCornerRadius.stretchTo(0f) + backgroundFarCornerRadius.stretchTo(0f) } /** * Updates resting arrow and background size not accounting for stretch */ - internal fun updateRestingArrowDimens( - backgroundWidth: Float, - backgroundHeight: Float, - backgroundEdgeCornerRadius: Float, - backgroundDragCornerRadius: Float, - arrowLength: Float, - arrowHeight: Float, - horizontalTranslation: Float, + internal fun setRestingDimens( + restingParams: EdgePanelParams.BackIndicatorDimens, animate: Boolean ) { - this.arrowLength.updateRestingPosition(arrowLength, animate) - this.arrowHeight.updateRestingPosition(arrowHeight, animate) - this.backgroundWidth.updateRestingPosition(backgroundWidth, animate) - this.backgroundHeight.updateRestingPosition(backgroundHeight, animate) - this.backgroundEdgeCornerRadius.updateRestingPosition(backgroundEdgeCornerRadius, animate) - this.backgroundDragCornerRadius.updateRestingPosition(backgroundDragCornerRadius, animate) - this.horizontalTranslation.updateRestingPosition(horizontalTranslation, animate) + horizontalTranslation.updateRestingPosition(restingParams.horizontalTranslation, animate) + arrowLength.updateRestingPosition(restingParams.arrowDimens.length, animate) + arrowHeight.updateRestingPosition(restingParams.arrowDimens.height, animate) + backgroundWidth.updateRestingPosition(restingParams.backgroundDimens.width, animate) + backgroundHeight.updateRestingPosition(restingParams.backgroundDimens.height, animate) + backgroundEdgeCornerRadius.updateRestingPosition( + restingParams.backgroundDimens.edgeCornerRadius, + animate + ) + backgroundFarCornerRadius.updateRestingPosition( + restingParams.backgroundDimens.farCornerRadius, + animate + ) } fun animateVertically(yPos: Float) = verticalTranslation.stretchTo(yPos) @@ -262,7 +310,7 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : override fun onDraw(canvas: Canvas) { var edgeCorner = backgroundEdgeCornerRadius.pos - val farCorner = backgroundDragCornerRadius.pos + val farCorner = backgroundFarCornerRadius.pos val halfHeight = backgroundHeight.pos / 2 canvas.save() @@ -337,4 +385,13 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : ) addRoundRect(this@toPathWithRoundCorners, corners, Path.Direction.CW) } + + fun cancelAlphaAnimations() { + alphaAnimation.cancel() + alpha = 1f + } + + fun fadeOut() { + alphaAnimation.animateToFinalPosition(0f) + } } 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 100411b1cb93d..f1dd5ffd2077b 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt @@ -31,7 +31,7 @@ import android.view.MotionEvent import android.view.VelocityTracker import android.view.View import android.view.WindowManager -import android.view.animation.AccelerateInterpolator +import android.view.animation.DecelerateInterpolator import android.view.animation.PathInterpolator import android.window.BackEvent import androidx.dynamicanimation.animation.DynamicAnimation @@ -68,7 +68,7 @@ private const val GESTURE_DURATION_FOR_CLICK_MS = 400 /** * The min duration arrow remains on screen during a fling event. */ -private const val FLING_PAUSE_DURATION_MS = 50L +private const val FLING_MIN_APPEARANCE_DURATION = 235L /** * The min duration arrow remains on screen during a fling event. @@ -90,7 +90,9 @@ private const val ARROW_DISAPPEAR_DAMPING_RATIO = SpringForce.DAMPING_RATIO_NO_B */ private val RUBBER_BAND_INTERPOLATOR = PathInterpolator(1.0f / 5.0f, 1.0f, 1.0f, 1.0f) -private val ACCELERATE_INTERPOLATOR = AccelerateInterpolator(0.7f) +private val DECELERATE_INTERPOLATOR = DecelerateInterpolator() + +private val DECELERATE_INTERPOLATOR_SLOW = DecelerateInterpolator(0.7f) class BackPanelController private constructor( context: Context, @@ -160,6 +162,8 @@ class BackPanelController private constructor( private var startX = 0f private var startY = 0f + private var gestureStartTime = 0L + private val failsafeRunnable = Runnable { onFailsafe() } private enum class GestureState { @@ -182,19 +186,29 @@ class BackPanelController private constructor( COMMITTED, /* back action currently cancelling, arrow soon to be GONE */ - CANCELLED + CANCELLED; + + /** + * @return true if the current state responds to touch move events in some way (e.g. by + * stretching the back indicator) + */ + fun isInteractive(): Boolean { + return when (this) { + ENTRY, ACTIVE, INACTIVE -> true + GONE, FLUNG, COMMITTED, CANCELLED -> false + } + } } /** * Wrapper around OnAnimationEndListener which runs the given runnable after a delay. The * runnable is not called if the animation is cancelled */ - class DelayedOnAnimationEndListener( + inner class DelayedOnAnimationEndListener internal constructor( private val handler: Handler, private val runnable: Runnable, - private val delay: Long + private val minDuration: Long ) : DynamicAnimation.OnAnimationEndListener { - override fun onAnimationEnd( animation: DynamicAnimation<*>, canceled: Boolean, @@ -203,11 +217,15 @@ class BackPanelController private constructor( ) { animation.removeEndListener(this) if (!canceled) { + // Total elapsed time of the gesture and the animation + val totalElapsedTime = SystemClock.uptimeMillis() - gestureStartTime + // The delay between finishing this animation and starting the runnable + val delay = max(0, minDuration - totalElapsedTime) handler.postDelayed(runnable, delay) } } - fun runNow() { + internal fun runNow() { runnable.run() } } @@ -216,7 +234,7 @@ class BackPanelController private constructor( DelayedOnAnimationEndListener( mainHandler, { updateArrowState(GestureState.COMMITTED) }, - delay = FLING_PAUSE_DURATION_MS + minDuration = FLING_MIN_APPEARANCE_DURATION ) private val setGoneEndListener = @@ -226,21 +244,21 @@ class BackPanelController private constructor( cancelFailsafe() updateArrowState(GestureState.GONE) }, - delay = 0 + minDuration = 0 ) // Vibration private var vibrationTime: Long = 0 - // Minimum size of the screen's width or height - private var screenSize = 0 + // Minimum of the screen's width or the predefined threshold + private var fullyStretchedThreshold = 0f /** * Used for initialization and configuration changes */ private fun updateConfiguration() { params.update(resources) - initializeBackAnimation() + updateBackAnimationSwipeThresholds() mView.updateArrowPaint(params.arrowThickness) } @@ -284,6 +302,7 @@ class BackPanelController private constructor( resetOnDown() startX = event.x startY = event.y + gestureStartTime = SystemClock.uptimeMillis() // Reset the arrow to the side updateArrowState(GestureState.ENTRY) @@ -308,40 +327,39 @@ class BackPanelController private constructor( } private fun updateArrowStateOnMove(yTranslation: Float, xTranslation: Float) { + if (!currentState.isInteractive()) + return + when (currentState) { - GestureState.GONE, GestureState.FLUNG, GestureState.COMMITTED, GestureState.CANCELLED -> - return + // Check if we should transition from ENTRY to ACTIVE + GestureState.ENTRY -> + if (xTranslation > params.swipeTriggerThreshold) { + updateArrowState(GestureState.ACTIVE) + } + + // Abort if we had continuous motion toward the edge for a while, OR the direction + // in Y is bigger than X * 2 + GestureState.ACTIVE -> + if ((totalTouchDelta < 0 && -totalTouchDelta > params.minDeltaForSwitch) || + (yTranslation > xTranslation * 2) + ) { + updateArrowState(GestureState.INACTIVE) + } + + // Re-activate if we had continuous motion away from the edge for a while + GestureState.INACTIVE -> + if (totalTouchDelta > 0 && totalTouchDelta > params.minDeltaForSwitch) { + updateArrowState(GestureState.ACTIVE) + } + + // By default assume the current direction is kept + else -> {} } - - updateArrowState( - when { - // Check if we should transition from ENTRY to ACTIVE - currentState == GestureState.ENTRY && xTranslation > params.swipeTriggerThreshold -> - GestureState.ACTIVE - - // Abort if we had continuous motion toward the edge for a while, OR the direction - // in Y is bigger than X * 2 - currentState == GestureState.ACTIVE && - ((totalTouchDelta < 0 && -totalTouchDelta > params.minDeltaForSwitch) || - (yTranslation > xTranslation * 2)) -> - GestureState.INACTIVE - - // Re-activate if we had continuous motion away from the edge for a while - currentState == GestureState.INACTIVE && - (totalTouchDelta > 0 && totalTouchDelta > params.minDeltaForSwitch) -> - GestureState.ACTIVE - - // By default assume the current direction is kept - else -> currentState - } - ) } private fun handleMoveEvent(event: MotionEvent) { - when (currentState) { - GestureState.GONE, GestureState.FLUNG, GestureState.COMMITTED, - GestureState.CANCELLED -> return - } + if (!currentState.isInteractive()) + return val x = event.x val y = event.y @@ -372,24 +390,25 @@ class BackPanelController private constructor( updateArrowStateOnMove(yTranslation, xTranslation) when (currentState) { - GestureState.ACTIVE -> setActiveStretch(fullScreenStretchProgress(xTranslation)) + GestureState.ACTIVE -> + stretchActiveBackIndicator(fullScreenStretchProgress(xTranslation)) GestureState.ENTRY -> - setEntryStretch(preThresholdStretchProgress(xTranslation)) - GestureState.INACTIVE -> mView.resetStretch() + stretchEntryBackIndicator(preThresholdStretchProgress(xTranslation)) + GestureState.INACTIVE -> + mView.resetStretch() } // set y translation setVerticalTranslation(yOffset) } - fun setVerticalTranslation(yOffset: Float) { + private fun setVerticalTranslation(yOffset: Float) { val yTranslation = abs(yOffset) - val maxYOffset = (mView.height / 2) - (params.entryBackgroundHeight / 2) + val maxYOffset = (mView.height - params.entryIndicator.backgroundDimens.height) / 2f val yProgress = saturate(yTranslation / (maxYOffset * RUBBER_BAND_AMOUNT)) mView.animateVertically( - RUBBER_BAND_INTERPOLATOR.getInterpolation(yProgress) * maxYOffset * sign( - yOffset - ) + RUBBER_BAND_INTERPOLATOR.getInterpolation(yProgress) * maxYOffset * + sign(yOffset) ) } @@ -397,13 +416,10 @@ class BackPanelController private constructor( * @return the relative position of the drag from the time after the arrow is activated until * the arrow is fully stretched (between 0.0 - 1.0f) */ - fun fullScreenStretchProgress(xTranslation: Float): Float { + private fun fullScreenStretchProgress(xTranslation: Float): Float { return saturate( (xTranslation - params.swipeTriggerThreshold) / - (min( - params.fullyStretchedThreshold, - screenSize.toFloat() - ) - params.swipeTriggerThreshold) + (fullyStretchedThreshold - params.swipeTriggerThreshold) ) } @@ -411,57 +427,38 @@ class BackPanelController private constructor( * Tracks the relative position of the drag from the entry until the threshold where the arrow * activates (between 0.0 - 1.0f) */ - fun preThresholdStretchProgress(xTranslation: Float): Float { + private fun preThresholdStretchProgress(xTranslation: Float): Float { return saturate(xTranslation / params.swipeTriggerThreshold) } - fun setActiveStretch(progress: Float) { - val stretch = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress) + private fun stretchActiveBackIndicator(progress: Float) { + val rubberBandIterpolation = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress) mView.setStretch( - arrowLengthStretch = stretch * (params.stretchedArrowLength - params.activeArrowLength), - arrowHeightStretch = stretch * (params.stretchedArrowHeight - params.activeArrowHeight), - backgroundWidthStretch = - stretch * (params.stretchBackgroundWidth - params.activeBackgroundWidth), - backgroundHeightStretch = - stretch * (params.stretchBackgroundHeight - params.activeBackgroundHeight), - backgroundEdgeCornerRadiusStretch = - stretch * (params.stretchEdgeCorners - params.activeEdgeCorners), - backgroundDragCornerRadiusStretch = - stretch * (params.stretchFarCorners - params.activeFarCorners), - horizontalTranslationStretch = stretch * (params.stretchMargin - params.activeMargin) + horizontalTranslationStretchAmount = rubberBandIterpolation, + arrowStretchAmount = rubberBandIterpolation, + backgroundWidthStretchAmount = DECELERATE_INTERPOLATOR_SLOW.getInterpolation(progress), + params.fullyStretchedIndicator ) } - fun setEntryStretch(progress: Float) { - val bgStretch = ACCELERATE_INTERPOLATOR.getInterpolation(progress) - val arrowStretch = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress) + private fun stretchEntryBackIndicator(progress: Float) { mView.setStretch( - arrowLengthStretch = - arrowStretch * (params.activeArrowLength - params.entryArrowLength), - arrowHeightStretch = - arrowStretch * (params.activeArrowHeight - params.entryArrowHeight), - backgroundWidthStretch = - bgStretch * (params.preThresholdBackgroundWidth - params.entryBackgroundWidth), - backgroundHeightStretch = - bgStretch * (params.preThresholdBackgroundHeight - params.entryBackgroundHeight), - backgroundEdgeCornerRadiusStretch = - bgStretch * (params.preThresholdEdgeCorners - params.entryEdgeCorners), - backgroundDragCornerRadiusStretch = - bgStretch * (params.preThresholdFarCorners - params.entryFarCorners), - horizontalTranslationStretch = - bgStretch * (params.preThresholdMargin - params.entryMargin) + horizontalTranslationStretchAmount = 0f, + arrowStretchAmount = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress), + backgroundWidthStretchAmount = DECELERATE_INTERPOLATOR.getInterpolation(progress), + params.preThresholdIndicator ) } fun setBackAnimation(backAnimation: BackAnimation?) { this.backAnimation = backAnimation - initializeBackAnimation() + updateBackAnimationSwipeThresholds() } - private fun initializeBackAnimation() { + private fun updateBackAnimationSwipeThresholds() { backAnimation?.setSwipeThresholds( params.swipeTriggerThreshold, - params.swipeProgressThreshold + fullyStretchedThreshold ) } @@ -541,79 +538,68 @@ class BackPanelController private constructor( private fun updateYPosition(touchY: Float) { var yPosition = touchY - params.fingerOffset - yPosition = Math.max(yPosition, params.minArrowYPosition.toFloat()) + yPosition = max(yPosition, params.minArrowYPosition.toFloat()) yPosition -= layoutParams.height / 2.0f layoutParams.y = constrain(yPosition.toInt(), 0, displaySize.y) } override fun setDisplaySize(displaySize: Point) { this.displaySize.set(displaySize.x, displaySize.y) - screenSize = Math.min(displaySize.x, displaySize.y) + fullyStretchedThreshold = min(displaySize.x.toFloat(), params.swipeProgressThreshold) + updateBackAnimationSwipeThresholds() } /** * Updates resting arrow and background size not accounting for stretch */ private fun updateRestingArrowDimens(animated: Boolean, currentState: GestureState) { - mView.updateRestingArrowDimens( - backgroundWidth = - when (currentState) { - GestureState.GONE, GestureState.ENTRY -> params.entryBackgroundWidth - else -> params.activeBackgroundWidth - }, - backgroundHeight = - when (currentState) { - GestureState.GONE, GestureState.ENTRY -> params.entryBackgroundHeight - else -> params.activeBackgroundHeight - }, - backgroundEdgeCornerRadius = - when (currentState) { - GestureState.GONE, GestureState.ENTRY, GestureState.INACTIVE -> - params.entryEdgeCorners - else -> - params.activeEdgeCorners - }, - backgroundDragCornerRadius = - when (currentState) { - GestureState.GONE, GestureState.ENTRY -> params.entryFarCorners - else -> params.activeFarCorners - }, - arrowLength = - when (currentState) { - GestureState.ACTIVE, GestureState.INACTIVE, GestureState.COMMITTED, - GestureState.FLUNG -> params.activeArrowLength - GestureState.CANCELLED -> params.cancelledArrowLength - GestureState.GONE, GestureState.ENTRY -> params.entryArrowLength - }, - arrowHeight = - when (currentState) { - GestureState.ACTIVE, GestureState.INACTIVE, GestureState.COMMITTED, - GestureState.FLUNG -> params.activeArrowHeight - GestureState.CANCELLED -> params.cancelledArrowHeight - GestureState.GONE, GestureState.ENTRY -> params.entryArrowHeight - }, - horizontalTranslation = - when (currentState) { - GestureState.GONE -> -params.activeBackgroundWidth - // Position the cancelled/committed arrow slightly further off the screen so we - // do not see part of it bouncing - GestureState.CANCELLED, GestureState.COMMITTED -> - -params.activeBackgroundWidth * 1.5f - GestureState.FLUNG -> params.stretchMargin - GestureState.ACTIVE -> params.activeMargin - GestureState.ENTRY, GestureState.INACTIVE -> params.entryMargin - }, - animate = animated - ) if (animated) { when (currentState) { GestureState.ENTRY, GestureState.ACTIVE, GestureState.FLUNG -> mView.setArrowStiffness(ARROW_APPEAR_STIFFNESS, ARROW_APPEAR_DAMPING_RATIO) + GestureState.CANCELLED -> mView.fadeOut() else -> mView.setArrowStiffness( - ARROW_DISAPPEAR_STIFFNESS, ARROW_DISAPPEAR_DAMPING_RATIO) + ARROW_DISAPPEAR_STIFFNESS, + ARROW_DISAPPEAR_DAMPING_RATIO + ) } } + mView.setRestingDimens( + restingParams = EdgePanelParams.BackIndicatorDimens( + horizontalTranslation = when (currentState) { + GestureState.GONE -> -params.activeIndicator.backgroundDimens.width + // Position the committed arrow slightly further off the screen so we do not + // see part of it bouncing + GestureState.COMMITTED -> + -params.activeIndicator.backgroundDimens.width * 1.5f + GestureState.FLUNG -> params.fullyStretchedIndicator.horizontalTranslation + GestureState.ACTIVE -> params.activeIndicator.horizontalTranslation + GestureState.ENTRY, GestureState.INACTIVE, GestureState.CANCELLED -> + params.entryIndicator.horizontalTranslation + }, + arrowDimens = when (currentState) { + GestureState.ACTIVE, GestureState.INACTIVE, + GestureState.COMMITTED, GestureState.FLUNG -> params.activeIndicator.arrowDimens + GestureState.CANCELLED -> params.cancelledArrowDimens + GestureState.GONE, GestureState.ENTRY -> params.entryIndicator.arrowDimens + }, + backgroundDimens = when (currentState) { + GestureState.GONE, GestureState.ENTRY -> params.entryIndicator.backgroundDimens + else -> + params.activeIndicator.backgroundDimens.copy( + edgeCornerRadius = + if (currentState == GestureState.INACTIVE || + currentState == GestureState.CANCELLED + ) + params.entryIndicator.backgroundDimens.edgeCornerRadius + else + params.activeIndicator.backgroundDimens.edgeCornerRadius + ) + } + ), + animate = animated + ) } /** @@ -628,7 +614,12 @@ class BackPanelController private constructor( if (DEBUG) Log.d(TAG, "updateArrowState $currentState -> $newState") previousState = currentState currentState = newState - mView.visibility = if (currentState == GestureState.GONE) View.GONE else View.VISIBLE + if (currentState == GestureState.GONE) { + mView.cancelAlphaAnimations() + mView.visibility = View.GONE + } else { + mView.visibility = View.VISIBLE + } when (currentState) { // Transitioning to GONE never animates since the arrow is (presumably) already off the diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt index 51566b0f8393f..a3fb58d5b0150 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt @@ -4,66 +4,36 @@ import android.content.res.Resources import com.android.systemui.R data class EdgePanelParams(private var resources: Resources) { + + data class ArrowDimens( + val length: Float = 0f, + val height: Float = 0f + ) + + data class BackgroundDimens( + val width: Float = 0f, + val height: Float = 0f, + val edgeCornerRadius: Float = 0f, + val farCornerRadius: Float = 0f + ) + + data class BackIndicatorDimens( + val horizontalTranslation: Float = 0f, + val arrowDimens: ArrowDimens = ArrowDimens(), + val backgroundDimens: BackgroundDimens = BackgroundDimens() + ) + var arrowThickness: Float = 0f private set - var entryArrowLength: Float = 0f + var entryIndicator = BackIndicatorDimens() private set - var entryArrowHeight: Float = 0f + var activeIndicator = BackIndicatorDimens() private set - var activeArrowLength: Float = 0f + var preThresholdIndicator = BackIndicatorDimens() private set - var activeArrowHeight: Float = 0f - private set - var stretchedArrowLength: Float = 0f - private set - var stretchedArrowHeight: Float = 0f - private set - var cancelledArrowLength: Float = 0f - private set - var cancelledArrowHeight: Float = 0f - private set - var entryMargin: Float = 0f - private set - var entryBackgroundWidth: Float = 0f - private set - var entryBackgroundHeight: Float = 0f - private set - var entryEdgeCorners: Float = 0f - private set - var entryFarCorners: Float = 0f - private set - var preThresholdMargin: Float = 0f - private set - var preThresholdBackgroundWidth: Float = 0f - private set - var preThresholdBackgroundHeight: Float = 0f - private set - var preThresholdEdgeCorners: Float = 0f - private set - var preThresholdFarCorners: Float = 0f - private set - var activeMargin: Float = 0f - private set - var activeBackgroundWidth: Float = 0f - private set - var activeBackgroundHeight: Float = 0f - private set - var activeEdgeCorners: Float = 0f - private set - var activeFarCorners: Float = 0f - private set - var fullyStretchedThreshold: Float = 0f - private set - var stretchMargin: Float = 0f - private set - var stretchBackgroundWidth: Float = 0f - private set - var stretchBackgroundHeight: Float = 0f - private set - var stretchEdgeCorners: Float = 0f - private set - var stretchFarCorners: Float = 0f + var fullyStretchedIndicator = BackIndicatorDimens() private set + var cancelledArrowDimens = ArrowDimens() // navigation bar edge constants var arrowPaddingEnd: Int = 0 @@ -98,42 +68,73 @@ data class EdgePanelParams(private var resources: Resources) { fun update(resources: Resources) { this.resources = resources arrowThickness = getDimen(R.dimen.navigation_edge_arrow_thickness) - entryArrowLength = getDimen(R.dimen.navigation_edge_entry_arrow_length) - entryArrowHeight = getDimen(R.dimen.navigation_edge_entry_arrow_height) - activeArrowLength = getDimen(R.dimen.navigation_edge_active_arrow_length) - activeArrowHeight = getDimen(R.dimen.navigation_edge_active_arrow_height) - stretchedArrowLength = getDimen(R.dimen.navigation_edge_stretched_arrow_length) - stretchedArrowHeight = getDimen(R.dimen.navigation_edge_stretched_arrow_height) - cancelledArrowLength = getDimen(R.dimen.navigation_edge_cancelled_arrow_length) - cancelledArrowHeight = getDimen(R.dimen.navigation_edge_cancelled_arrow_height) - entryMargin = getDimen(R.dimen.navigation_edge_entry_margin) - entryBackgroundWidth = getDimen(R.dimen.navigation_edge_entry_background_width) - entryBackgroundHeight = getDimen(R.dimen.navigation_edge_entry_background_height) - entryEdgeCorners = getDimen(R.dimen.navigation_edge_entry_edge_corners) - entryFarCorners = getDimen(R.dimen.navigation_edge_entry_far_corners) - preThresholdMargin = getDimen(R.dimen.navigation_edge_pre_threshold_margin) - preThresholdBackgroundWidth = - getDimen(R.dimen.navigation_edge_pre_threshold_background_width) - preThresholdBackgroundHeight = - getDimen(R.dimen.navigation_edge_pre_threshold_background_height) - preThresholdEdgeCorners = getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners) - preThresholdFarCorners = getDimen(R.dimen.navigation_edge_pre_threshold_far_corners) - activeMargin = getDimen(R.dimen.navigation_edge_active_margin) - activeBackgroundWidth = getDimen(R.dimen.navigation_edge_active_background_width) - activeBackgroundHeight = getDimen(R.dimen.navigation_edge_active_background_height) - activeEdgeCorners = getDimen(R.dimen.navigation_edge_active_edge_corners) - activeFarCorners = getDimen(R.dimen.navigation_edge_active_far_corners) - fullyStretchedThreshold = getDimen(R.dimen.navigation_edge_stretch_threshold) - stretchMargin = getDimen(R.dimen.navigation_edge_stretch_margin) - stretchBackgroundWidth = getDimen(R.dimen.navigation_edge_stretch_background_width) - stretchBackgroundHeight = getDimen(R.dimen.navigation_edge_stretch_background_height) - stretchEdgeCorners = getDimen(R.dimen.navigation_edge_stretch_left_corners) - stretchFarCorners = getDimen(R.dimen.navigation_edge_stretch_right_corners) arrowPaddingEnd = getPx(R.dimen.navigation_edge_panel_padding) minArrowYPosition = getPx(R.dimen.navigation_edge_arrow_min_y) fingerOffset = getPx(R.dimen.navigation_edge_finger_offset) swipeTriggerThreshold = getDimen(R.dimen.navigation_edge_action_drag_threshold) swipeProgressThreshold = getDimen(R.dimen.navigation_edge_action_progress_threshold) minDeltaForSwitch = getPx(R.dimen.navigation_edge_minimum_x_delta_for_switch) + + entryIndicator = BackIndicatorDimens( + horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin), + arrowDimens = ArrowDimens( + length = getDimen(R.dimen.navigation_edge_entry_arrow_length), + height = getDimen(R.dimen.navigation_edge_entry_arrow_height), + ), + backgroundDimens = BackgroundDimens( + width = getDimen(R.dimen.navigation_edge_entry_background_width), + height = getDimen(R.dimen.navigation_edge_entry_background_height), + edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners), + farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners) + ) + ) + + activeIndicator = BackIndicatorDimens( + horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin), + arrowDimens = ArrowDimens( + length = getDimen(R.dimen.navigation_edge_active_arrow_length), + height = getDimen(R.dimen.navigation_edge_active_arrow_height), + ), + backgroundDimens = BackgroundDimens( + width = getDimen(R.dimen.navigation_edge_active_background_width), + height = getDimen(R.dimen.navigation_edge_active_background_height), + edgeCornerRadius = getDimen(R.dimen.navigation_edge_active_edge_corners), + farCornerRadius = getDimen(R.dimen.navigation_edge_active_far_corners) + + ) + ) + + preThresholdIndicator = BackIndicatorDimens( + horizontalTranslation = getDimen(R.dimen.navigation_edge_pre_threshold_margin), + arrowDimens = ArrowDimens( + length = entryIndicator.arrowDimens.length, + height = entryIndicator.arrowDimens.height, + ), + backgroundDimens = BackgroundDimens( + width = getDimen(R.dimen.navigation_edge_pre_threshold_background_width), + height = getDimen(R.dimen.navigation_edge_pre_threshold_background_height), + edgeCornerRadius = getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners), + farCornerRadius = getDimen(R.dimen.navigation_edge_pre_threshold_far_corners) + ) + ) + + fullyStretchedIndicator = BackIndicatorDimens( + horizontalTranslation = getDimen(R.dimen.navigation_edge_stretch_margin), + arrowDimens = ArrowDimens( + length = getDimen(R.dimen.navigation_edge_stretched_arrow_length), + height = getDimen(R.dimen.navigation_edge_stretched_arrow_height), + ), + backgroundDimens = BackgroundDimens( + width = getDimen(R.dimen.navigation_edge_stretch_background_width), + height = getDimen(R.dimen.navigation_edge_stretch_background_height), + edgeCornerRadius = getDimen(R.dimen.navigation_edge_stretch_edge_corners), + farCornerRadius = getDimen(R.dimen.navigation_edge_stretch_far_corners) + ) + ) + + cancelledArrowDimens = ArrowDimens( + length = getDimen(R.dimen.navigation_edge_cancelled_arrow_length), + height = getDimen(R.dimen.navigation_edge_cancelled_arrow_height) + ) } }