diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt index b8c1c7f1d7..aa2555e865 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt @@ -39,4 +39,13 @@ interface BubbleBarFlyoutPositioner { /** The color of the flyout when collapsed. */ val collapsedColor: Int + + /** The elevation of the flyout when collapsed. */ + val collapsedElevation: Float + + /** + * The distance the flyout must pass from its collapsed position until it can start revealing + * the triangle. + */ + val distanceToRevealTriangle: Float } diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt index 6723f57dd5..8d84ddf8ab 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt @@ -40,8 +40,6 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly ConstraintLayout(context) { private companion object { - // the minimum progress of the expansion animation before the triangle is made visible. - const val MIN_EXPANSION_PROGRESS_FOR_TRIANGLE = 0.1f // the minimum progress of the expansion animation before the content starts fading in. const val MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA = 0.75f } @@ -92,6 +90,11 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_max_width) } + private val flyoutElevation by + lazy(LazyThreadSafetyMode.NONE) { + context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_elevation).toFloat() + } + /** The bounds of the background rect. */ private val backgroundRect = RectF() private val cornerRadius: Float @@ -108,6 +111,10 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly private var collapsedCornerRadius = 0f /** The color of the flyout when collapsed. */ private var collapsedColor = 0 + /** The elevation of the flyout when collapsed. */ + private var collapsedElevation = 0f + /** The minimum progress of the expansion animation before the triangle is made visible. */ + private var minExpansionProgressForTriangle = 0f /** The corner radius of the background according to the progress of the animation. */ private val currentCornerRadius @@ -141,8 +148,7 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly val padding = context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_padding) // add extra padding to the bottom of the view to include the triangle setPadding(padding, padding, padding, padding + triangleHeight - triangleOverlap) - translationZ = - context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_elevation).toFloat() + translationZ = flyoutElevation RoundedArrowDrawable.addDownPointingRoundedTriangleToPath( triangleWidth.toFloat(), @@ -182,6 +188,12 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly collapsedSize = positioner.collapsedSize collapsedCornerRadius = collapsedSize / 2 collapsedColor = positioner.collapsedColor + collapsedElevation = positioner.collapsedElevation + + // calculate the expansion progress required before we start showing the triangle as part of + // the expansion animation + minExpansionProgressForTriangle = + positioner.distanceToRevealTriangle / tyToCollapsedPosition // post the request to start the expand animation to the looper so the view can measure // itself @@ -240,6 +252,9 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly message.alpha = alpha avatar.alpha = alpha + translationZ = + collapsedElevation + (flyoutElevation - collapsedElevation) * expansionProgress + invalidate() } @@ -275,7 +290,7 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly currentCornerRadius, backgroundPaint, ) - if (expansionProgress >= MIN_EXPANSION_PROGRESS_FOR_TRIANGLE) { + if (expansionProgress >= minExpansionProgressForTriangle) { drawTriangle(canvas) } canvas.restore() @@ -291,9 +306,20 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly } else { width - currentCornerRadius - triangleWidth } - // instead of scaling the triangle, increasingly reveal it from the background, starting - // with half the size. this has the effect of the triangle scaling. - val triangleY = height - triangleHeight - 0.5f * triangleHeight * (1 - expansionProgress) + // instead of scaling the triangle, increasingly reveal it from the background. this has the + // effect of the triangle scaling. + + // the translation y of the triangle before we start revealing it. align its bottom with the + // bottom of the rect + val triangleYCollapsed = height - triangleHeight - (triangleHeight - triangleOverlap) + // the translation y of the triangle when it's fully revealed + val triangleYExpanded = height - triangleHeight + val interpolatedExpansion = + ((expansionProgress - minExpansionProgressForTriangle) / + (1 - minExpansionProgressForTriangle)) + .coerceIn(0f, 1f) + val triangleY = + triangleYCollapsed + (triangleYExpanded - triangleYCollapsed) * interpolatedExpansion canvas.translate(triangleX, triangleY) canvas.drawPath(triangle, backgroundPaint) triangleOutline.setPath(triangle) @@ -309,7 +335,7 @@ class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFly currentCornerRadius, Path.Direction.CW, ) - if (expansionProgress >= MIN_EXPANSION_PROGRESS_FOR_TRIANGLE) { + if (expansionProgress >= minExpansionProgressForTriangle) { path.addPath(triangleOutline.mPath) } outline.setPath(path) diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt index 50e2dcf7b4..6aba6a3c78 100644 --- a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt +++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt @@ -224,7 +224,7 @@ class BubbleBarFlyoutViewScreenshotTest(emulationSpec: DeviceEmulationSpec) { BubbleBarFlyoutMessage( senderAvatar = ColorDrawable(Color.RED), senderName = "sender", - message = "collapsed 90% on left", + message = "expanded 90% on left", isGroupChat = true, ) ) {} @@ -249,7 +249,7 @@ class BubbleBarFlyoutViewScreenshotTest(emulationSpec: DeviceEmulationSpec) { BubbleBarFlyoutMessage( senderAvatar = ColorDrawable(Color.RED), senderName = "sender", - message = "collapsed 80% on right", + message = "expanded 80% on right", isGroupChat = true, ) ) {} @@ -265,5 +265,7 @@ class BubbleBarFlyoutViewScreenshotTest(emulationSpec: DeviceEmulationSpec) { override val targetTy = 0f override val collapsedSize = 30f override val collapsedColor = Color.BLUE + override val collapsedElevation = 1f + override val distanceToRevealTriangle = 10f } } diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt index 0f02444b30..d857ae5579 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt @@ -55,6 +55,8 @@ class BubbleBarFlyoutControllerTest { override val distanceToCollapsedPosition = PointF(100f, 200f) override val collapsedSize = 30f override val collapsedColor = Color.BLUE + override val collapsedElevation = 1f + override val distanceToRevealTriangle = 50f } flyoutController = BubbleBarFlyoutController(flyoutContainer, positioner) }