Set additional bubble translation during stash

Fixes bubbles stash translation not getting cleared up after stash
animation finishes.

Bubbles are clipped using an outline animator during the stash
animation. They need separate translation applied to keep them within
the bounds of the bubble bar that is also shrinking and moving.

Set the translation for the bubbles in the stash controller so we can
reset the translation after the animation has finished.

Bug: 365829293
Flag: com.android.wm.shell.enable_bubble_bar
Test: TransientBubbleStashControllerTest
Test: have bubbles in bubble bar, trigger a new auto expanding bubble,
  check translation for bubbles
Change-Id: Ic194afdb4d650fcd525355d8bae08dd651d1ea05
This commit is contained in:
Ats Jenk
2024-09-11 10:24:05 -07:00
parent d72a0400eb
commit aad71bc532
5 changed files with 75 additions and 58 deletions
@@ -187,6 +187,9 @@ public class BubbleBarView extends FrameLayout {
private BubbleView mDismissedByDragBubbleView;
private float mAlphaDuringDrag = 1f;
/** Additional translation in the y direction that is applied to each bubble */
private float mBubbleOffsetY;
private Controller mController;
private int mPreviousLayoutDirection = LayoutDirection.UNDEFINED;
@@ -334,6 +337,16 @@ public class BubbleBarView extends FrameLayout {
mBubbleBarBackground.setAlpha((int) (255 * alpha));
}
/**
* Sets offset of each bubble view in the y direction from the base position in the bar.
*/
public void setBubbleOffsetY(float offsetY) {
mBubbleOffsetY = offsetY;
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).setTranslationY(getBubbleTranslationY());
}
}
/**
* Sets new icon sizes and newBubbleBarPadding between icons and bubble bar borders.
*
@@ -994,10 +1007,7 @@ public class BubbleBarView extends FrameLayout {
final float expandedWidth = expandedWidth();
final float collapsedWidth = collapsedWidth();
int childCount = getChildCount();
float viewBottom = mBubbleBarBounds.height() + (isExpanded() ? mPointerSize : 0);
float bubbleBarAnimatedTop = viewBottom - getBubbleBarHeight();
// When translating X & Y the scale is ignored, so need to deduct it from the translations
final float ty = bubbleBarAnimatedTop + mBubbleBarPadding - getScaleIconShift();
final float ty = getBubbleTranslationY();
final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl());
// elevation state is opposite to widthState - when expanded all icons are flat
float elevationState = (1 - widthState);
@@ -1131,6 +1141,13 @@ public class BubbleBarView extends FrameLayout {
return mBubbleBarPadding + translationX - getScaleIconShift();
}
private float getBubbleTranslationY() {
float viewBottom = mBubbleBarBounds.height() + (isExpanded() ? mPointerSize : 0);
float bubbleBarAnimatedTop = viewBottom - getBubbleBarHeight();
// When translating X & Y the scale is ignored, so need to deduct it from the translations
return mBubbleOffsetY + bubbleBarAnimatedTop + mBubbleBarPadding - getScaleIconShift();
}
/**
* Reorders the views to match the provided list.
*/
@@ -18,11 +18,8 @@ package com.android.launcher3.taskbar.bubbles;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static com.android.launcher3.taskbar.bubbles.BubbleView.STASH_TRANSLATION_Y;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
@@ -97,6 +94,8 @@ public class BubbleBarViewController {
this::updateBackgroundScaleY);
private final AnimatedFloat mBubbleBarTranslationY = new AnimatedFloat(
this::updateTranslationY);
private final AnimatedFloat mBubbleOffsetY = new AnimatedFloat(
this::updateBubbleOffsetY);
// Modified when swipe up is happening on the bubble bar or task bar.
private float mBubbleBarSwipeUpTranslationY;
@@ -299,6 +298,10 @@ public class BubbleBarViewController {
return mBubbleBarTranslationY;
}
public AnimatedFloat getBubbleOffsetY() {
return mBubbleOffsetY;
}
public float getBubbleBarCollapsedWidth() {
return mBarView.collapsedWidth();
}
@@ -576,6 +579,10 @@ public class BubbleBarViewController {
mBarView.setBubbleAlpha(alpha);
}
private void updateBubbleOffsetY(float transY) {
mBarView.setBubbleOffsetY(transY);
}
private void updateBackgroundAlpha(float alpha) {
mBarView.setBackgroundAlpha(alpha);
}
@@ -874,14 +881,9 @@ public class BubbleBarViewController {
mBubbleStashController.getHandleBounds(stashedHandleBounds);
int childCount = mBarView.getChildCount();
float newChildWidth = (float) stashedHandleBounds.width() / childCount;
float stashTranslationY = -mBubbleStashController.getBubbleBarTranslationY();
AnimatorSet animatorSet = new AnimatorSet();
for (int i = 0; i < childCount; i++) {
BubbleView child = (BubbleView) mBarView.getChildAt(i);
final float startTransY = isStashed ? 0f : stashTranslationY;
final float endTransY = isStashed ? stashTranslationY : 0f;
animatorSet.play(
ObjectAnimator.ofFloat(child, STASH_TRANSLATION_Y, startTransY, endTransY));
animatorSet.play(
createRevealAnimForBubble(child, isStashed, stashedHandleBounds,
newChildWidth));
@@ -27,7 +27,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.LayoutInflater;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
@@ -50,27 +49,12 @@ public class BubbleView extends ConstraintLayout {
public static final int DEFAULT_PATH_SIZE = 100;
public static FloatProperty<BubbleView> STASH_TRANSLATION_Y = new FloatProperty<>(
"stashTranslationY") {
@Override
public void setValue(BubbleView bubbleView, float transY) {
bubbleView.setStashTranslationY(transY);
}
@Override
public Float get(BubbleView bubbleView) {
return bubbleView.mStashTranslationY;
}
};
private final ImageView mBubbleIcon;
private final ImageView mAppIcon;
private int mBubbleSize;
private float mDragTranslationX;
private float mOffsetX;
private float mTranslationY;
private float mStashTranslationY;
private DotRenderer mDotRenderer;
private DotRenderer.DrawParams mDrawParams;
@@ -177,24 +161,6 @@ public class BubbleView extends ConstraintLayout {
setTranslationX(mDragTranslationX + mOffsetX);
}
/**
* Set translation in y direction during stash and unstash from handle
*/
public void setStashTranslationY(float translationY) {
mStashTranslationY = translationY;
applyTranslationY();
}
@Override
public void setTranslationY(float translationY) {
mTranslationY = translationY;
applyTranslationY();
}
private void applyTranslationY() {
super.setTranslationY(mTranslationY + mStashTranslationY);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -47,7 +47,7 @@ import kotlin.math.max
class TransientBubbleStashController(
private val taskbarHotseatDimensionsProvider: TaskbarHotseatDimensionsProvider,
private val context: Context
private val context: Context,
) : BubbleStashController {
private lateinit var bubbleBarViewController: BubbleBarViewController
@@ -70,6 +70,7 @@ class TransientBubbleStashController(
private lateinit var bubbleBarBubbleAlpha: AnimatedFloat
private lateinit var bubbleBarBackgroundAlpha: AnimatedFloat
private lateinit var bubbleBarTranslationYAnimator: AnimatedFloat
private lateinit var bubbleBarBubbleTranslationY: AnimatedFloat
private lateinit var bubbleBarBackgroundScaleX: AnimatedFloat
private lateinit var bubbleBarBackgroundScaleY: AnimatedFloat
private val handleCenterFromScreenBottom =
@@ -143,13 +144,14 @@ class TransientBubbleStashController(
taskbarInsetsController: TaskbarInsetsController,
bubbleBarViewController: BubbleBarViewController,
bubbleStashedHandleViewController: BubbleStashedHandleViewController?,
controllersAfterInitAction: ControllersAfterInitAction
controllersAfterInitAction: ControllersAfterInitAction,
) {
this.taskbarInsetsController = taskbarInsetsController
this.bubbleBarViewController = bubbleBarViewController
this.bubbleStashedHandleViewController = bubbleStashedHandleViewController
this.controllersAfterInitAction = controllersAfterInitAction
bubbleBarTranslationYAnimator = bubbleBarViewController.bubbleBarTranslationY
bubbleBarBubbleTranslationY = bubbleBarViewController.bubbleOffsetY
// bubble bar has only alpha property, getting it at index 0
bubbleBarAlpha = bubbleBarViewController.bubbleBarAlpha.get(/* index= */ 0)
bubbleBarBubbleAlpha = bubbleBarViewController.bubbleBarBubbleAlpha
@@ -170,7 +172,7 @@ class TransientBubbleStashController(
bubbleBarTranslationYAnimator.animateToValue(bubbleBarTranslationY),
bubbleBarAlpha.animateToValue(1f),
bubbleBarBubbleAlpha.animateToValue(1f),
bubbleBarBackgroundAlpha.animateToValue(1f)
bubbleBarBackgroundAlpha.animateToValue(1f),
)
} else {
isStashed = true
@@ -334,6 +336,16 @@ class TransientBubbleStashController(
}
)
// Animate bubble translation to keep reveal animation in the bounds of the bar
val bubbleTyStart = if (isStashed) 0f else -bubbleBarTranslationY
val bubbleTyEnd = if (isStashed) -bubbleBarTranslationY else 0f
animatorSet.play(
bubbleBarBubbleTranslationY.animateToValue(bubbleTyStart, bubbleTyEnd).apply {
this.duration = duration
this.interpolator = EMPHASIZED
}
)
animatorSet.play(
bubbleStashedHandleViewController?.createRevealAnimToIsStashed(isStashed)?.apply {
this.duration = duration
@@ -373,6 +385,9 @@ class TransientBubbleStashController(
// reset bubble view alpha
bubbleBarBubbleAlpha.updateValue(1f)
bubbleBarBackgroundAlpha.updateValue(1f)
// reset stash translation
translationYDuringStash.updateValue(0f)
bubbleBarBubbleTranslationY.updateValue(0f)
bubbleBarViewController.isExpanded = false
}
taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
@@ -32,6 +32,7 @@ import com.android.launcher3.taskbar.TaskbarInsetsController
import com.android.launcher3.taskbar.bubbles.BubbleBarView
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController
import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController
import com.android.launcher3.taskbar.bubbles.BubbleView
import com.android.launcher3.util.MultiValueAlpha
import com.android.wm.shell.shared.animation.PhysicsAnimator
import com.android.wm.shell.shared.animation.PhysicsAnimatorTestUtils
@@ -55,8 +56,8 @@ class TransientBubbleStashControllerTest {
companion object {
const val TASKBAR_BOTTOM_SPACE = 5
const val BUBBLE_BAR_WIDTH = 200f
const val BUBBLE_BAR_HEIGHT = 100f
const val BUBBLE_BAR_WIDTH = 200
const val BUBBLE_BAR_HEIGHT = 100
const val HOTSEAT_TRANSLATION_Y = -45f
const val TASK_BAR_TRANSLATION_Y = -TASKBAR_BOTTOM_SPACE
const val HANDLE_VIEW_WIDTH = 150
@@ -77,10 +78,12 @@ class TransientBubbleStashControllerTest {
private val context = ApplicationProvider.getApplicationContext<Context>()
private lateinit var bubbleBarView: BubbleBarView
private lateinit var stashedHandleView: StashedHandleView
private lateinit var bubbleView: BubbleView
private lateinit var barTranslationY: AnimatedFloat
private lateinit var barScaleX: AnimatedFloat
private lateinit var barScaleY: AnimatedFloat
private lateinit var barAlpha: MultiValueAlpha
private lateinit var bubbleOffsetY: AnimatedFloat
private lateinit var bubbleAlpha: AnimatedFloat
private lateinit var backgroundAlpha: AnimatedFloat
private lateinit var stashedHandleAlpha: MultiValueAlpha
@@ -105,7 +108,7 @@ class TransientBubbleStashControllerTest {
taskbarInsetsController,
bubbleBarViewController,
bubbleStashedHandleViewController,
ImmediateAction()
ImmediateAction(),
)
}
@@ -161,11 +164,13 @@ class TransientBubbleStashControllerTest {
mTransientBubbleStashController.isStashed = false
whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
val bubbleInitialTranslation = bubbleView.translationY
// When stash
getInstrumentation().runOnMainSync {
mTransientBubbleStashController.updateStashedAndExpandedState(
stash = true,
expand = false
expand = false,
)
}
@@ -184,6 +189,9 @@ class TransientBubbleStashControllerTest {
// Handle view is visible
assertThat(stashedHandleView.translationY).isEqualTo(0)
assertThat(stashedHandleView.alpha).isEqualTo(1)
// Bubble view is reset
assertThat(bubbleView.translationY).isEqualTo(bubbleInitialTranslation)
assertThat(bubbleView.alpha).isEqualTo(1f)
}
@Test
@@ -274,7 +282,7 @@ class TransientBubbleStashControllerTest {
val height = mTransientBubbleStashController.getTouchableHeight()
// Then bubble bar height is returned
assertThat(height).isEqualTo(BUBBLE_BAR_HEIGHT.toInt())
assertThat(height).isEqualTo(BUBBLE_BAR_HEIGHT)
}
private fun advanceTimeBy(advanceMs: Long) {
@@ -285,20 +293,26 @@ class TransientBubbleStashControllerTest {
private fun setUpBubbleBarView() {
getInstrumentation().runOnMainSync {
bubbleBarView = BubbleBarView(context)
bubbleBarView.layoutParams = FrameLayout.LayoutParams(0, 0)
bubbleBarView.layoutParams =
FrameLayout.LayoutParams(BUBBLE_BAR_WIDTH, BUBBLE_BAR_HEIGHT)
bubbleView = BubbleView(context)
bubbleBarView.addBubble(bubbleView)
bubbleBarView.layout(0, 0, BUBBLE_BAR_WIDTH, BUBBLE_BAR_HEIGHT)
}
}
private fun setUpStashedHandleView() {
getInstrumentation().runOnMainSync {
stashedHandleView = StashedHandleView(context)
stashedHandleView.layoutParams = FrameLayout.LayoutParams(0, 0)
stashedHandleView.layoutParams =
FrameLayout.LayoutParams(HANDLE_VIEW_WIDTH, HANDLE_VIEW_HEIGHT)
}
}
private fun setUpBubbleBarController() {
barTranslationY =
AnimatedFloat(Runnable { bubbleBarView.translationY = barTranslationY.value })
bubbleOffsetY = AnimatedFloat { value -> bubbleBarView.setBubbleOffsetY(value) }
barScaleX = AnimatedFloat { value -> bubbleBarView.scaleX = value }
barScaleY = AnimatedFloat { value -> bubbleBarView.scaleY = value }
barAlpha = MultiValueAlpha(bubbleBarView, 1 /* num alpha channels */)
@@ -307,13 +321,16 @@ class TransientBubbleStashControllerTest {
whenever(bubbleBarViewController.hasBubbles()).thenReturn(true)
whenever(bubbleBarViewController.bubbleBarTranslationY).thenReturn(barTranslationY)
whenever(bubbleBarViewController.bubbleOffsetY).thenReturn(bubbleOffsetY)
whenever(bubbleBarViewController.bubbleBarBackgroundScaleX).thenReturn(barScaleX)
whenever(bubbleBarViewController.bubbleBarBackgroundScaleY).thenReturn(barScaleY)
whenever(bubbleBarViewController.bubbleBarAlpha).thenReturn(barAlpha)
whenever(bubbleBarViewController.bubbleBarBubbleAlpha).thenReturn(bubbleAlpha)
whenever(bubbleBarViewController.bubbleBarBackgroundAlpha).thenReturn(backgroundAlpha)
whenever(bubbleBarViewController.bubbleBarCollapsedWidth).thenReturn(BUBBLE_BAR_WIDTH)
whenever(bubbleBarViewController.bubbleBarCollapsedHeight).thenReturn(BUBBLE_BAR_HEIGHT)
whenever(bubbleBarViewController.bubbleBarCollapsedWidth)
.thenReturn(BUBBLE_BAR_WIDTH.toFloat())
whenever(bubbleBarViewController.bubbleBarCollapsedHeight)
.thenReturn(BUBBLE_BAR_HEIGHT.toFloat())
whenever(bubbleBarViewController.createRevealAnimatorForStashChange(any()))
.thenReturn(AnimatorSet())
}