Seamless handoff between stashed handle and taskbar.

Bug: 267806083
Bug: 246634367
Test: manual
Change-Id: I0c3d7a19aaa36a323c6fb3349852727f56842bb2
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index 2d20582..c03c916 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -55,6 +55,9 @@
     private val stashedHandleWidth =
         context.resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width)
 
+    private val stashedHandleHeight =
+        context.resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_height)
+
     init {
         paint.color = context.getColor(R.color.taskbar_background)
         paint.flags = Paint.ANTI_ALIAS_FLAG
@@ -102,8 +105,8 @@
     /** Draws the background with the given paint and height, on the provided canvas. */
     fun draw(canvas: Canvas) {
         canvas.save()
-        canvas.translate(0f, canvas.height - backgroundHeight - bottomMargin)
         if (!isTransientTaskbar || transientBackgroundBounds.isEmpty) {
+            canvas.translate(0f, canvas.height - backgroundHeight - bottomMargin)
             // Draw the background behind taskbar content.
             canvas.drawRect(0f, 0f, canvas.width.toFloat(), backgroundHeight, paint)
 
@@ -114,12 +117,21 @@
             canvas.translate(canvas.width - rightCornerRadius, -rightCornerRadius)
             canvas.drawPath(invertedRightCornerPath, paint)
         } else {
-            // Approximates the stash/unstash animation to transform the background.
+            // backgroundHeight is a value from [0...maxBackgroundHeight], so we can use it as a
+            // proxy to figure out the animation progress of the stash/unstash animation.
             val progress = backgroundHeight / maxBackgroundHeight
+
+            // At progress 0, we draw the background as the stashed handle.
+            // At progress 1, we draw the background as the full taskbar.
+            val newBackgroundHeight =
+                mapRange(progress, stashedHandleHeight.toFloat(), maxBackgroundHeight)
             val fullWidth = transientBackgroundBounds.width()
             val newWidth = mapRange(progress, stashedHandleWidth.toFloat(), fullWidth.toFloat())
-            val delta = fullWidth - newWidth
-            canvas.translate(0f, bottomMargin * ((1f - progress) / 2f))
+            val halfWidthDelta = (fullWidth - newWidth) / 2f
+            val radius = newBackgroundHeight / 2f
+            val bottomMarginProgress = bottomMargin * ((1f - progress) / 2f)
+
+            canvas.translate(0f, canvas.height - bottomMargin + bottomMarginProgress)
 
             // Draw shadow.
             val shadowAlpha =
@@ -131,20 +143,20 @@
                 setColorAlphaBound(Color.BLACK, Math.round(shadowAlpha))
             )
 
-            // Draw background.
-            val radius = backgroundHeight / 2f
+            // Aligns the bottom with the bottom of the stashed handle.
+            val bottom =
+                (-mapRange(1f - progress, 0f, stashedHandleHeight / 2f) + translationYForSwipe)
 
             canvas.drawRoundRect(
-                transientBackgroundBounds.left + (delta / 2f),
-                translationYForSwipe,
-                transientBackgroundBounds.right - (delta / 2f),
-                backgroundHeight + translationYForSwipe,
+                transientBackgroundBounds.left + halfWidthDelta,
+                bottom - newBackgroundHeight,
+                transientBackgroundBounds.right - halfWidthDelta,
+                bottom,
                 radius,
                 radius,
                 paint
             )
         }
-
         canvas.restore()
     }