diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java index 71867fe54b..dc7600a3a1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java @@ -1303,7 +1303,10 @@ public class BubbleBarView extends FrameLayout { return totalIconSize + totalSpace + horizontalPadding; } - private float collapsedWidth() { + /** + * Get width of the bubble bar if it is collapsed + */ + float collapsedWidth() { final int bubbleChildCount = getBubbleChildCount(); final float horizontalPadding = 2 * mBubbleBarPadding; // If there are more than 2 bubbles, the first 2 should be visible when collapsed, diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java index 2502e4a775..c55faa66a6 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java @@ -80,6 +80,7 @@ public class BubbleBarViewController { // These are exposed to {@link BubbleStashController} to animate for stashing/un-stashing private final MultiValueAlpha mBubbleBarAlpha; + private final AnimatedFloat mBubbleBarScaleX = new AnimatedFloat(this::updateScaleX); private final AnimatedFloat mBubbleBarScaleY = new AnimatedFloat(this::updateScaleY); private final AnimatedFloat mBubbleBarTranslationY = new AnimatedFloat( this::updateTranslationY); @@ -257,6 +258,10 @@ public class BubbleBarViewController { return mBubbleBarAlpha; } + public AnimatedFloat getBubbleBarScaleX() { + return mBubbleBarScaleX; + } + public AnimatedFloat getBubbleBarScaleY() { return mBubbleBarScaleY; } @@ -265,6 +270,10 @@ public class BubbleBarViewController { return mBubbleBarTranslationY; } + public float getBubbleBarCollapsedWidth() { + return mBarView.collapsedWidth(); + } + public float getBubbleBarCollapsedHeight() { return mBarView.getBubbleBarCollapsedHeight(); } @@ -309,6 +318,14 @@ public class BubbleBarViewController { return mBarView.getBubbleBarLocation(); } + /** + * @return {@code true} if bubble bar is on the left edge of the screen, {@code false} if on + * the right + */ + public boolean isBubbleBarOnLeft() { + return mBarView.getBubbleBarLocation().isOnLeft(mBarView.isLayoutRtl()); + } + /** * Update bar {@link BubbleBarLocation} */ @@ -510,6 +527,10 @@ public class BubbleBarViewController { + mBubbleBarStashTranslationY); } + private void updateScaleX(float scale) { + mBarView.setScaleX(scale); + } + private void updateScaleY(float scale) { mBarView.setScaleY(scale); } diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java index 16af248fbf..73984ea872 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java @@ -172,6 +172,13 @@ public class BubbleStashedHandleViewController { mRegionSamplingHelper = null; } + /** + * Returns the width of the stashed handle. + */ + public int getStashedWidth() { + return mStashedHandleWidth; + } + /** * Returns the height of the stashed handle. */ diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt index b8fd1cb1ed..ab27eb206c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt @@ -67,7 +67,8 @@ class TransientBubbleStashController( // bubble bar properties private lateinit var bubbleBarAlpha: MultiPropertyFactory.MultiProperty private lateinit var bubbleBarTranslationYAnimator: AnimatedFloat - private lateinit var bubbleBarScale: AnimatedFloat + private lateinit var bubbleBarScaleX: AnimatedFloat + private lateinit var bubbleBarScaleY: AnimatedFloat private val handleCenterFromScreenBottom = context.resources.getDimensionPixelSize(R.dimen.bubblebar_stashed_size) / 2f @@ -148,7 +149,8 @@ class TransientBubbleStashController( bubbleBarTranslationYAnimator = bubbleBarViewController.bubbleBarTranslationY // bubble bar has only alpha property, getting it at index 0 bubbleBarAlpha = bubbleBarViewController.bubbleBarAlpha.get(/* index= */ 0) - bubbleBarScale = bubbleBarViewController.bubbleBarScaleY + bubbleBarScaleX = bubbleBarViewController.bubbleBarScaleX + bubbleBarScaleY = bubbleBarViewController.bubbleBarScaleY stashedHeight = bubbleStashedHandleViewController?.stashedHeight ?: 0 stashHandleViewAlpha = bubbleStashedHandleViewController?.stashedHandleAlpha?.get(0) } @@ -158,7 +160,8 @@ class TransientBubbleStashController( if (isBubblesShowingOnHome || isBubblesShowingOnOverview) { isStashed = false animatorSet.playTogether( - bubbleBarScale.animateToValue(1f), + bubbleBarScaleX.animateToValue(1f), + bubbleBarScaleY.animateToValue(1f), bubbleBarTranslationYAnimator.animateToValue(bubbleBarTranslationY), bubbleBarAlpha.animateToValue(1f) ) @@ -178,7 +181,8 @@ class TransientBubbleStashController( stashHandleViewAlpha?.value = 0f this.bubbleBarTranslationYAnimator.updateValue(bubbleBarTranslationY) bubbleBarAlpha.setValue(1f) - bubbleBarScale.updateValue(1f) + bubbleBarScaleX.updateValue(1f) + bubbleBarScaleY.updateValue(1f) isStashed = false onIsStashedChanged() } @@ -188,7 +192,8 @@ class TransientBubbleStashController( stashHandleViewAlpha?.value = 1f this.bubbleBarTranslationYAnimator.updateValue(getStashTranslation()) bubbleBarAlpha.setValue(0f) - bubbleBarScale.updateValue(getStashScale()) + bubbleBarScaleX.updateValue(getStashScaleX()) + bubbleBarScaleY.updateValue(getStashScaleY()) isStashed = true onIsStashedChanged() } @@ -258,7 +263,13 @@ class TransientBubbleStashController( } @VisibleForTesting - fun getStashScale(): Float { + fun getStashScaleX(): Float { + val handleWidth = bubbleStashedHandleViewController?.stashedWidth ?: 0 + return handleWidth / bubbleBarViewController.bubbleBarCollapsedWidth + } + + @VisibleForTesting + fun getStashScaleY(): Float { val handleHeight = bubbleStashedHandleViewController?.stashedHeight ?: 0 return handleHeight / bubbleBarViewController.bubbleBarCollapsedHeight } @@ -298,12 +309,12 @@ class TransientBubbleStashController( } ) - val scaleTarget = if (isStashed) getStashScale() else 1f + val pivotX = if (bubbleBarViewController.isBubbleBarOnLeft) 0f else 1f animatorSet.play( - bubbleBarScale.animateToValue(scaleTarget).apply { + createScaleAnimator(isStashed).apply { this.duration = duration this.interpolator = EMPHASIZED - this.setBubbleBarPivotDuringAnim(0.5f, 1f) + this.setBubbleBarPivotDuringAnim(pivotX, 1f) } ) @@ -351,6 +362,15 @@ class TransientBubbleStashController( .build(translationYDuringStash, AnimatedFloat.VALUE) } + private fun createScaleAnimator(isStashed: Boolean): AnimatorSet { + val scaleXTarget = if (isStashed) getStashScaleX() else 1f + val scaleYTarget = if (isStashed) getStashScaleY() else 1f + return AnimatorSet().apply { + play(bubbleBarScaleX.animateToValue(scaleXTarget)) + play(bubbleBarScaleY.animateToValue(scaleYTarget)) + } + } + private fun onIsStashedChanged() { controllersAfterInitAction.runAfterInit { taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged() diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt index 63c21979c2..262d8da668 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt @@ -54,9 +54,11 @@ class TransientBubbleStashControllerTest { companion object { const val TASKBAR_BOTTOM_SPACE = 5 + const val BUBBLE_BAR_WIDTH = 200f const val BUBBLE_BAR_HEIGHT = 100f const val HOTSEAT_TRANSLATION_Y = -45f const val TASK_BAR_TRANSLATION_Y = -TASKBAR_BOTTOM_SPACE + const val HANDLE_VIEW_WIDTH = 150 const val HANDLE_VIEW_HEIGHT = 4 const val BUBBLE_BAR_STASHED_TRANSLATION_Y = -2.5f } @@ -75,7 +77,8 @@ class TransientBubbleStashControllerTest { private lateinit var bubbleBarView: BubbleBarView private lateinit var stashedHandleView: StashedHandleView private lateinit var barTranslationY: AnimatedFloat - private lateinit var barScale: AnimatedFloat + private lateinit var barScaleX: AnimatedFloat + private lateinit var barScaleY: AnimatedFloat private lateinit var barAlpha: MultiValueAlpha private lateinit var stashedHandleAlpha: MultiValueAlpha private lateinit var stashedHandleScale: AnimatedFloat @@ -173,8 +176,8 @@ class TransientBubbleStashControllerTest { assertThat(mTransientBubbleStashController.isStashed).isTrue() assertThat(bubbleBarView.translationY).isEqualTo(BUBBLE_BAR_STASHED_TRANSLATION_Y) assertThat(bubbleBarView.alpha).isEqualTo(0f) - assertThat(bubbleBarView.scaleX).isEqualTo(mTransientBubbleStashController.getStashScale()) - assertThat(bubbleBarView.scaleY).isEqualTo(mTransientBubbleStashController.getStashScale()) + assertThat(bubbleBarView.scaleX).isEqualTo(mTransientBubbleStashController.getStashScaleX()) + assertThat(bubbleBarView.scaleY).isEqualTo(mTransientBubbleStashController.getStashScaleY()) // Handle view is visible assertThat(stashedHandleView.translationY).isEqualTo(0) assertThat(stashedHandleView.alpha).isEqualTo(1) @@ -195,7 +198,7 @@ class TransientBubbleStashControllerTest { // Then assertThat(barTranslationY.isAnimating).isTrue() - assertThat(barScale.isAnimating).isTrue() + assertThat(barScaleX.isAnimating).isTrue() // Wait until animation ends advanceTimeBy(BubbleStashController.BAR_STASH_DURATION) @@ -242,8 +245,8 @@ class TransientBubbleStashControllerTest { // Then all property values are updated assertThat(bubbleBarView.translationY).isEqualTo(BUBBLE_BAR_STASHED_TRANSLATION_Y) assertThat(bubbleBarView.alpha).isEqualTo(0) - assertThat(bubbleBarView.scaleX).isEqualTo(mTransientBubbleStashController.getStashScale()) - assertThat(bubbleBarView.scaleY).isEqualTo(mTransientBubbleStashController.getStashScale()) + assertThat(bubbleBarView.scaleX).isEqualTo(mTransientBubbleStashController.getStashScaleX()) + assertThat(bubbleBarView.scaleY).isEqualTo(mTransientBubbleStashController.getStashScaleY()) // Handle is visible at correct Y position assertThat(stashedHandleView.alpha).isEqualTo(1) assertThat(stashedHandleView.translationY).isEqualTo(0) @@ -293,20 +296,16 @@ class TransientBubbleStashControllerTest { private fun setUpBubbleBarController() { barTranslationY = AnimatedFloat(Runnable { bubbleBarView.translationY = barTranslationY.value }) - barScale = - AnimatedFloat( - Runnable { - val scale: Float = barScale.value - bubbleBarView.scaleX = scale - bubbleBarView.scaleY = scale - } - ) + barScaleX = AnimatedFloat { value -> bubbleBarView.scaleX = value } + barScaleY = AnimatedFloat { value -> bubbleBarView.scaleY = value } barAlpha = MultiValueAlpha(bubbleBarView, 1 /* num alpha channels */) whenever(bubbleBarViewController.hasBubbles()).thenReturn(true) whenever(bubbleBarViewController.bubbleBarTranslationY).thenReturn(barTranslationY) - whenever(bubbleBarViewController.bubbleBarScaleY).thenReturn(barScale) + whenever(bubbleBarViewController.bubbleBarScaleX).thenReturn(barScaleX) + whenever(bubbleBarViewController.bubbleBarScaleY).thenReturn(barScaleY) whenever(bubbleBarViewController.bubbleBarAlpha).thenReturn(barAlpha) + whenever(bubbleBarViewController.bubbleBarCollapsedWidth).thenReturn(BUBBLE_BAR_WIDTH) whenever(bubbleBarViewController.bubbleBarCollapsedHeight).thenReturn(BUBBLE_BAR_HEIGHT) } @@ -316,7 +315,7 @@ class TransientBubbleStashControllerTest { stashedHandleScale = AnimatedFloat( Runnable { - val scale: Float = barScale.value + val scale: Float = barScaleX.value bubbleBarView.scaleX = scale bubbleBarView.scaleY = scale } @@ -326,6 +325,7 @@ class TransientBubbleStashControllerTest { whenever(bubbleStashedHandleViewController.stashedHandleAlpha) .thenReturn(stashedHandleAlpha) whenever(bubbleStashedHandleViewController.physicsAnimator).thenReturn(stashPhysicsAnimator) + whenever(bubbleStashedHandleViewController.stashedWidth).thenReturn(HANDLE_VIEW_WIDTH) whenever(bubbleStashedHandleViewController.stashedHeight).thenReturn(HANDLE_VIEW_HEIGHT) whenever(bubbleStashedHandleViewController.setTranslationYForSwipe(any())).thenAnswer { invocation ->