Merge "New switch animation for bubble bar bubbles" into main
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 21ec84d..9e2d23b 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -266,6 +266,8 @@
<dimen name="bubble_bar_expanded_view_handle_height">4dp</dimen>
<!-- Width of the expanded bubble bar view shown when the bubble is expanded. -->
<dimen name="bubble_bar_expanded_view_width">412dp</dimen>
+ <!-- Offset of the expanded view when it starts sliding in as part of the switch animation -->
+ <dimen name="bubble_bar_expanded_view_switch_offset">48dp</dimen>
<!-- Minimum width of the bubble bar manage menu. -->
<dimen name="bubble_bar_manage_menu_min_width">200dp</dimen>
<!-- Size of the dismiss icon in the bubble bar manage menu. -->
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
index a313bd0..4d7c7fa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.bubbles.bar;
import static android.view.View.ALPHA;
+import static android.view.View.INVISIBLE;
import static android.view.View.SCALE_X;
import static android.view.View.SCALE_Y;
import static android.view.View.TRANSLATION_X;
@@ -25,6 +26,7 @@
import static android.view.View.Y;
import static com.android.wm.shell.bubbles.bar.BubbleBarExpandedView.CORNER_RADIUS;
+import static com.android.wm.shell.bubbles.bar.BubbleBarExpandedView.TASK_VIEW_ALPHA;
import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED;
import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED_DECELERATE;
@@ -32,7 +34,6 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
@@ -42,11 +43,12 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
+import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.BubbleOverflow;
import com.android.wm.shell.bubbles.BubblePositioner;
import com.android.wm.shell.bubbles.BubbleViewProvider;
import com.android.wm.shell.bubbles.animation.AnimatableScaleMatrix;
-import com.android.wm.shell.shared.animation.Interpolators;
import com.android.wm.shell.shared.animation.PhysicsAnimator;
import com.android.wm.shell.shared.magnetictarget.MagnetizedObject.MagneticTarget;
@@ -59,7 +61,7 @@
private static final float EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT = 0.1f;
private static final float EXPANDED_VIEW_ANIMATE_OUT_SCALE_AMOUNT = .75f;
- private static final int EXPANDED_VIEW_ALPHA_ANIMATION_DURATION = 150;
+ private static final int EXPANDED_VIEW_EXPAND_ALPHA_DURATION = 150;
private static final int EXPANDED_VIEW_SNAP_TO_DISMISS_DURATION = 400;
private static final int EXPANDED_VIEW_ANIMATE_TO_REST_DURATION = 400;
private static final int EXPANDED_VIEW_DISMISS_DURATION = 250;
@@ -72,6 +74,17 @@
private static final float DISMISS_VIEW_SCALE = 1.25f;
private static final int HANDLE_ALPHA_ANIMATION_DURATION = 100;
+ private static final float SWITCH_OUT_SCALE = 0.97f;
+ private static final long SWITCH_OUT_SCALE_DURATION = 200L;
+ private static final long SWITCH_OUT_ALPHA_DURATION = 100L;
+ private static final long SWITCH_OUT_HANDLE_ALPHA_DURATION = 50L;
+ private static final long SWITCH_IN_ANIM_DELAY = 50L;
+ private static final long SWITCH_IN_TX_DURATION = 350L;
+ private static final long SWITCH_IN_ALPHA_DURATION = 50L;
+ // Keep this handle alpha delay at least as long as alpha animation for both expanded views.
+ private static final long SWITCH_IN_HANDLE_ALPHA_DELAY = 150L;
+ private static final long SWITCH_IN_HANDLE_ALPHA_DURATION = 100L;
+
/** Spring config for the expanded view scale-in animation. */
private final PhysicsAnimator.SpringConfig mScaleInSpringConfig =
new PhysicsAnimator.SpringConfig(300f, 0.9f);
@@ -80,68 +93,24 @@
private final PhysicsAnimator.SpringConfig mScaleOutSpringConfig =
new PhysicsAnimator.SpringConfig(900f, 1f);
+ private final int mSwitchAnimPositionOffset;
+
/** Matrix used to scale the expanded view container with a given pivot point. */
private final AnimatableScaleMatrix mExpandedViewContainerMatrix = new AnimatableScaleMatrix();
- /** Animator for animating the expanded view's alpha (including the TaskView inside it). */
- private final ValueAnimator mExpandedViewAlphaAnimator = ValueAnimator.ofFloat(0f, 1f);
-
@Nullable
- private Animator mRunningDragAnimator;
+ private Animator mRunningAnimator;
- private final Context mContext;
- private final BubbleBarLayerView mLayerView;
private final BubblePositioner mPositioner;
private final int[] mTmpLocation = new int[2];
+ // TODO(b/381936992): remove expanded bubble state from this helper class
private BubbleViewProvider mExpandedBubble;
- private boolean mIsExpanded = false;
- public BubbleBarAnimationHelper(Context context,
- BubbleBarLayerView bubbleBarLayerView,
- BubblePositioner positioner) {
- mContext = context;
- mLayerView = bubbleBarLayerView;
+ public BubbleBarAnimationHelper(Context context, BubblePositioner positioner) {
mPositioner = positioner;
-
- mExpandedViewAlphaAnimator.setDuration(EXPANDED_VIEW_ALPHA_ANIMATION_DURATION);
- mExpandedViewAlphaAnimator.setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED);
- mExpandedViewAlphaAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- BubbleBarExpandedView bbev = getExpandedView();
- if (bbev != null) {
- // We need to be Z ordered on top in order for alpha animations to work.
- bbev.setSurfaceZOrderedOnTop(true);
- bbev.setAnimating(true);
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- BubbleBarExpandedView bbev = getExpandedView();
- if (bbev != null) {
- // The surface needs to be Z ordered on top for alpha values to work on the
- // TaskView, and if we're temporarily hidden, we are still on the screen
- // with alpha = 0f until we animate back. Stay Z ordered on top so the alpha
- // = 0f remains in effect.
- if (mIsExpanded) {
- bbev.setSurfaceZOrderedOnTop(false);
- }
-
- bbev.setContentVisibility(mIsExpanded);
- bbev.setAnimating(false);
- }
- }
- });
- mExpandedViewAlphaAnimator.addUpdateListener(valueAnimator -> {
- BubbleBarExpandedView bbev = getExpandedView();
- if (bbev != null) {
- float alpha = (float) valueAnimator.getAnimatedValue();
- bbev.setTaskViewAlpha(alpha);
- bbev.setAlpha(alpha);
- }
- });
+ mSwitchAnimPositionOffset = context.getResources().getDimensionPixelSize(
+ R.dimen.bubble_bar_expanded_view_switch_offset);
}
/**
@@ -154,18 +123,11 @@
if (bbev == null) {
return;
}
- mIsExpanded = true;
mExpandedViewContainerMatrix.setScaleX(0f);
mExpandedViewContainerMatrix.setScaleY(0f);
- updateExpandedView();
- bbev.setAnimating(true);
- bbev.setSurfaceZOrderedOnTop(true);
- bbev.setContentVisibility(false);
- bbev.setAlpha(0f);
- bbev.setTaskViewAlpha(0f);
- bbev.setVisibility(VISIBLE);
+ prepareForAnimateIn(bbev);
setScaleFromBubbleBar(mExpandedViewContainerMatrix,
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT);
@@ -173,7 +135,16 @@
bbev.setAnimationMatrix(mExpandedViewContainerMatrix);
bbev.animateExpansionWhenTaskViewVisible(() -> {
- mExpandedViewAlphaAnimator.start();
+ ObjectAnimator alphaAnim = createAlphaAnimator(bbev, /* visible= */ true);
+ alphaAnim.setDuration(EXPANDED_VIEW_EXPAND_ALPHA_DURATION);
+ alphaAnim.setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED);
+ alphaAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ bbev.setAnimating(false);
+ }
+ });
+ startNewAnimator(alphaAnim);
PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
@@ -188,7 +159,7 @@
})
.withEndActions(() -> {
bbev.setAnimationMatrix(null);
- updateExpandedView();
+ updateExpandedView(bbev);
if (afterAnimation != null) {
afterAnimation.run();
}
@@ -197,13 +168,24 @@
});
}
+ private void prepareForAnimateIn(BubbleBarExpandedView bbev) {
+ bbev.setAnimating(true);
+ updateExpandedView(bbev);
+ // We need to be Z ordered on top in order for taskView alpha to work.
+ // It is also set when the alpha animation starts, but needs to be set here to too avoid
+ // flickers.
+ bbev.setSurfaceZOrderedOnTop(true);
+ bbev.setTaskViewAlpha(0f);
+ bbev.setContentVisibility(false);
+ bbev.setVisibility(VISIBLE);
+ }
+
/**
* Collapses the currently expanded bubble.
*
* @param endRunnable a runnable to run at the end of the animation.
*/
public void animateCollapse(Runnable endRunnable) {
- mIsExpanded = false;
final BubbleBarExpandedView bbev = getExpandedView();
if (bbev == null) {
Log.w(TAG, "Trying to animate collapse without a bubble");
@@ -214,6 +196,19 @@
setScaleFromBubbleBar(mExpandedViewContainerMatrix, 1f);
+ bbev.setAnimating(true);
+
+ ObjectAnimator alphaAnim = createAlphaAnimator(bbev, /* visible= */ false);
+ alphaAnim.setDuration(EXPANDED_VIEW_EXPAND_ALPHA_DURATION);
+ alphaAnim.setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED);
+ alphaAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ bbev.setAnimating(false);
+ }
+ });
+ startNewAnimator(alphaAnim);
+
PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
.spring(AnimatableScaleMatrix.SCALE_X,
@@ -234,7 +229,6 @@
}
})
.start();
- mExpandedViewAlphaAnimator.reverse();
}
private void setScaleFromBubbleBar(AnimatableScaleMatrix matrix, float scale) {
@@ -246,6 +240,142 @@
}
/**
+ * Animate between two bubble views using a switch animation
+ *
+ * @param fromBubble bubble to hide
+ * @param toBubble bubble to show
+ * @param afterAnimation optional runnable after animation finishes
+ */
+ public void animateSwitch(BubbleViewProvider fromBubble, BubbleViewProvider toBubble,
+ @Nullable Runnable afterAnimation) {
+ /*
+ * Switch animation
+ *
+ * |.....................fromBubble scale to 0.97.....................|
+ * |fromBubble handle alpha 0|....fromBubble alpha to 0.....| |
+ * 0-------------------------50-----------------------100---150--------200----------250--400
+ * |..toBubble alpha to 1...| |toBubble handle alpha 1| |
+ * |................toBubble position +/-48 to 0...............|
+ */
+
+ mExpandedBubble = toBubble;
+ final BubbleBarExpandedView toBbev = toBubble.getBubbleBarExpandedView();
+ final BubbleBarExpandedView fromBbev = fromBubble.getBubbleBarExpandedView();
+ if (toBbev == null || fromBbev == null) {
+ return;
+ }
+
+ fromBbev.setAnimating(true);
+
+ prepareForAnimateIn(toBbev);
+ final float endTx = toBbev.getTranslationX();
+ final float startTx = getSwitchAnimationInitialTx(endTx);
+ toBbev.setTranslationX(startTx);
+ toBbev.getHandleView().setAlpha(0f);
+
+ toBbev.animateExpansionWhenTaskViewVisible(() -> {
+ AnimatorSet switchAnim = new AnimatorSet();
+ switchAnim.playTogether(switchOutAnimator(fromBbev), switchInAnimator(toBbev, endTx));
+
+ switchAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (afterAnimation != null) {
+ afterAnimation.run();
+ }
+ }
+ });
+ startNewAnimator(switchAnim);
+ });
+ }
+
+ private float getSwitchAnimationInitialTx(float endTx) {
+ if (mPositioner.isBubbleBarOnLeft()) {
+ return endTx - mSwitchAnimPositionOffset;
+ } else {
+ return endTx + mSwitchAnimPositionOffset;
+ }
+ }
+
+ private Animator switchOutAnimator(BubbleBarExpandedView bbev) {
+ setPivotToCenter(bbev);
+ AnimatorSet scaleAnim = new AnimatorSet();
+ scaleAnim.playTogether(
+ ObjectAnimator.ofFloat(bbev, SCALE_X, SWITCH_OUT_SCALE),
+ ObjectAnimator.ofFloat(bbev, SCALE_Y, SWITCH_OUT_SCALE)
+ );
+ scaleAnim.setInterpolator(Interpolators.ACCELERATE);
+ scaleAnim.setDuration(SWITCH_OUT_SCALE_DURATION);
+
+ ObjectAnimator alphaAnim = createAlphaAnimator(bbev, /* visible= */ false);
+ alphaAnim.setStartDelay(SWITCH_OUT_HANDLE_ALPHA_DURATION);
+ alphaAnim.setDuration(SWITCH_OUT_ALPHA_DURATION);
+
+ ObjectAnimator handleAlphaAnim = ObjectAnimator.ofFloat(bbev.getHandleView(), ALPHA, 0f)
+ .setDuration(SWITCH_OUT_HANDLE_ALPHA_DURATION);
+
+ AnimatorSet animator = new AnimatorSet();
+ animator.playTogether(scaleAnim, alphaAnim, handleAlphaAnim);
+
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ bbev.setAnimating(false);
+ }
+ });
+ return animator;
+ }
+
+ private Animator switchInAnimator(BubbleBarExpandedView bbev, float restingTx) {
+ ObjectAnimator positionAnim = ObjectAnimator.ofFloat(bbev, TRANSLATION_X, restingTx);
+ positionAnim.setInterpolator(Interpolators.EMPHASIZED_DECELERATE);
+ positionAnim.setStartDelay(SWITCH_IN_ANIM_DELAY);
+ positionAnim.setDuration(SWITCH_IN_TX_DURATION);
+
+ // Animate alpha directly to have finer control over surface z-ordering
+ ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(bbev, TASK_VIEW_ALPHA, 1f);
+ alphaAnim.setStartDelay(SWITCH_IN_ANIM_DELAY);
+ alphaAnim.setDuration(SWITCH_IN_ALPHA_DURATION);
+ alphaAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ bbev.setSurfaceZOrderedOnTop(true);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ bbev.setContentVisibility(true);
+ // The outgoing expanded view alpha animation is still in progress.
+ // Do not reset the surface z-order as otherwise the outgoing expanded view is
+ // placed on top.
+ }
+ });
+
+ ObjectAnimator handleAlphaAnim = ObjectAnimator.ofFloat(bbev.getHandleView(), ALPHA, 1f);
+ handleAlphaAnim.setStartDelay(SWITCH_IN_HANDLE_ALPHA_DELAY);
+ handleAlphaAnim.setDuration(SWITCH_IN_HANDLE_ALPHA_DURATION);
+ handleAlphaAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ bbev.setSurfaceZOrderedOnTop(false);
+ bbev.setAnimating(false);
+ }
+ });
+
+ AnimatorSet animator = new AnimatorSet();
+ animator.playTogether(positionAnim, alphaAnim, handleAlphaAnim);
+
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ updateExpandedView(bbev);
+ }
+ });
+ return animator;
+ }
+
+
+ /**
* Animate the expanded bubble when it is being dragged
*/
public void animateStartDrag() {
@@ -273,7 +403,7 @@
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(contentAnim, handleAnim);
animatorSet.addListener(new DragAnimatorListenerAdapter(bbev));
- startNewDragAnimation(animatorSet);
+ startNewAnimator(animatorSet);
}
/**
@@ -282,7 +412,6 @@
* @param endRunnable a runnable to run at the end of the animation
*/
public void animateDismiss(Runnable endRunnable) {
- mIsExpanded = false;
final BubbleBarExpandedView bbev = getExpandedView();
if (bbev == null) {
Log.w(TAG, "Trying to animate dismiss without a bubble");
@@ -335,7 +464,7 @@
bbev.setDragging(false);
}
});
- startNewDragAnimation(animatorSet);
+ startNewAnimator(animatorSet);
}
/**
@@ -409,7 +538,7 @@
}
}
});
- startNewDragAnimation(animatorSet);
+ startNewAnimator(animatorSet);
}
/**
@@ -435,7 +564,7 @@
animatorSet.setDuration(EXPANDED_VIEW_SNAP_TO_DISMISS_DURATION).setInterpolator(
EMPHASIZED_DECELERATE);
animatorSet.addListener(new DragAnimatorListenerAdapter(bbev));
- startNewDragAnimation(animatorSet);
+ startNewAnimator(animatorSet);
}
/**
@@ -443,14 +572,15 @@
*/
public void cancelAnimations() {
PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
- mExpandedViewAlphaAnimator.cancel();
BubbleBarExpandedView bbev = getExpandedView();
if (bbev != null) {
bbev.animate().cancel();
}
- if (mRunningDragAnimator != null) {
- mRunningDragAnimator.cancel();
- mRunningDragAnimator = null;
+ if (mRunningAnimator != null) {
+ if (mRunningAnimator.isRunning()) {
+ mRunningAnimator.cancel();
+ }
+ mRunningAnimator = null;
}
}
@@ -462,8 +592,7 @@
return null;
}
- private void updateExpandedView() {
- BubbleBarExpandedView bbev = getExpandedView();
+ private void updateExpandedView(BubbleBarExpandedView bbev) {
if (bbev == null) {
Log.w(TAG, "Trying to update the expanded view without a bubble");
return;
@@ -477,6 +606,8 @@
bbev.setLayoutParams(lp);
bbev.setX(position.x);
bbev.setY(position.y);
+ bbev.setScaleX(1f);
+ bbev.setScaleY(1f);
bbev.updateLocation();
bbev.maybeShowOverflow();
}
@@ -500,18 +631,54 @@
return new Size(width, height);
}
- private void startNewDragAnimation(Animator animator) {
+ private void startNewAnimator(Animator animator) {
cancelAnimations();
- mRunningDragAnimator = animator;
+ mRunningAnimator = animator;
animator.start();
}
+ /**
+ * Animate the alpha of the expanded view between visible (1) and invisible (0).
+ * {@link BubbleBarExpandedView} requires
+ * {@link com.android.wm.shell.bubbles.BubbleExpandedView#setSurfaceZOrderedOnTop(boolean)} to
+ * be called before alpha can be applied.
+ * Only supports alpha of 1 or 0. Otherwise we can't reset surface z-order at the end.
+ */
+ private ObjectAnimator createAlphaAnimator(BubbleBarExpandedView bubbleBarExpandedView,
+ boolean visible) {
+ ObjectAnimator animator = ObjectAnimator.ofFloat(bubbleBarExpandedView, TASK_VIEW_ALPHA,
+ visible ? 1f : 0f);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ // Move task view to the top of the window so alpha can be applied to it
+ bubbleBarExpandedView.setSurfaceZOrderedOnTop(true);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ bubbleBarExpandedView.setContentVisibility(visible);
+ if (!visible) {
+ // Hide the expanded view before we reset the z-ordering
+ bubbleBarExpandedView.setVisibility(INVISIBLE);
+ }
+ bubbleBarExpandedView.setSurfaceZOrderedOnTop(false);
+ }
+ });
+ return animator;
+ }
+
private static void setDragPivot(BubbleBarExpandedView bbev) {
bbev.setPivotX(bbev.getWidth() / 2f);
bbev.setPivotY(0f);
}
- private class DragAnimatorListenerAdapter extends AnimatorListenerAdapter {
+ private static void setPivotToCenter(BubbleBarExpandedView bbev) {
+ bbev.setPivotX(bbev.getWidth() / 2f);
+ bbev.setPivotY(bbev.getHeight() / 2f);
+ }
+
+ private static class DragAnimatorListenerAdapter extends AnimatorListenerAdapter {
private final BubbleBarExpandedView mBubbleBarExpandedView;
@@ -523,11 +690,9 @@
public void onAnimationStart(Animator animation) {
mBubbleBarExpandedView.setAnimating(true);
}
-
@Override
public void onAnimationEnd(Animator animation) {
mBubbleBarExpandedView.setAnimating(false);
- mRunningDragAnimator = null;
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index ed49417..2c0483c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -85,6 +85,22 @@
}
};
+ /**
+ * Property to set alpha for the task view
+ */
+ public static final FloatProperty<BubbleBarExpandedView> TASK_VIEW_ALPHA = new FloatProperty<>(
+ "taskViewAlpha") {
+ @Override
+ public void setValue(BubbleBarExpandedView bbev, float alpha) {
+ bbev.setTaskViewAlpha(alpha);
+ }
+
+ @Override
+ public Float get(BubbleBarExpandedView bbev) {
+ return bbev.mTaskView != null ? bbev.mTaskView.getAlpha() : bbev.getAlpha();
+ }
+ };
+
private static final String TAG = BubbleBarExpandedView.class.getSimpleName();
private static final int INVALID_TASK_ID = -1;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
index 0c05e3c..425afbe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
@@ -103,8 +103,7 @@
mPositioner = mBubbleController.getPositioner();
mBubbleLogger = bubbleLogger;
- mAnimationHelper = new BubbleBarAnimationHelper(context,
- this, mPositioner);
+ mAnimationHelper = new BubbleBarAnimationHelper(context, mPositioner);
mEducationViewController = new BubbleEducationViewController(context, (boolean visible) -> {
if (mExpandedView == null) return;
mExpandedView.setObscured(visible);
@@ -183,8 +182,14 @@
// Already showing this bubble, skip animating
return;
}
+ BubbleViewProvider previousBubble = null;
if (mExpandedBubble != null && !b.getKey().equals(mExpandedBubble.getKey())) {
- removeView(mExpandedView);
+ if (mIsExpanded) {
+ // Previous expanded view open, keep it visible to animate the switch
+ previousBubble = mExpandedBubble;
+ } else {
+ removeView(mExpandedView);
+ }
mExpandedView = null;
}
if (mExpandedView == null) {
@@ -246,7 +251,8 @@
mIsExpanded = true;
mBubbleController.getSysuiProxy().onStackExpandChanged(true);
- mAnimationHelper.animateExpansion(mExpandedBubble, () -> {
+
+ final Runnable afterAnimation = () -> {
if (mExpandedView == null) return;
// Touch delegate for the menu
BubbleBarHandleView view = mExpandedView.getHandleView();
@@ -256,7 +262,18 @@
mHandleTouchDelegate = new TouchDelegate(mHandleTouchBounds,
mExpandedView.getHandleView());
setTouchDelegate(mHandleTouchDelegate);
- });
+ };
+
+ if (previousBubble != null) {
+ final BubbleBarExpandedView previousExpandedView =
+ previousBubble.getBubbleBarExpandedView();
+ mAnimationHelper.animateSwitch(previousBubble, mExpandedBubble, () -> {
+ removeView(previousExpandedView);
+ afterAnimation.run();
+ });
+ } else {
+ mAnimationHelper.animateExpansion(mExpandedBubble, afterAnimation);
+ }
showScrim(true);
}