summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
author mpodolian <mpodolian@google.com> 2024-11-05 17:10:42 -0800
committer mpodolian <mpodolian@google.com> 2024-11-07 15:07:16 -0800
commit2db0d14b7a154e4d533aceabefe1c535521c6fe0 (patch)
tree53b86c9507345e76a5fef32f2fe21e35e0d1656b /libs
parente0519f2f49f93b288073440fd405cde908b63593 (diff)
Updated expanded bubble menu animation.
Added logic to the handle view and menu view to implement the updated animation specifications. Fixes: 345687667 Flag: com.android.wm.shell.enable_bubble_bar Test: BubbleBarHandleViewTest Test: Manual. Have few bubbles in the bubble bar. Expand one bubble and click on the handle view. Click anywhere outside of the menu. Click another bubble, observe handle view is properly placed. Click on the handle view. video: http://recall/-/gx8ASgewUeUS3QYohfrd1J/5dgZCNbnB9LxtPrpP6cUI Change-Id: Id9a5251792d05f45b515f0dfcf39d736f410a7dc
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml1
-rw-r--r--libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java128
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java155
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java17
7 files changed, 258 insertions, 97 deletions
diff --git a/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml b/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml
index 501bedd50f55..c2755ef6ccb6 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml
@@ -19,6 +19,7 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
+ android:clipChildren="false"
android:id="@+id/bubble_expanded_view">
<com.android.wm.shell.bubbles.bar.BubbleBarHandleView
diff --git a/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
index f1ecde49ce78..7aca921dccc7 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
@@ -14,20 +14,18 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<com.android.wm.shell.bubbles.bar.BubbleBarMenuView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
+<com.android.wm.shell.bubbles.bar.BubbleBarMenuView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
+ android:clipToPadding="false"
android:minWidth="@dimen/bubble_bar_manage_menu_min_width"
android:orientation="vertical"
- android:elevation="@dimen/bubble_manage_menu_elevation"
- android:paddingTop="@dimen/bubble_bar_manage_menu_padding_top"
- android:paddingHorizontal="@dimen/bubble_bar_manage_menu_padding"
- android:paddingBottom="@dimen/bubble_bar_manage_menu_padding"
- android:clipToPadding="false">
+ android:visibility="invisible"
+ tools:visibility="visible">
<LinearLayout
android:id="@+id/bubble_bar_manage_menu_bubble_section"
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 2a50e4d0d74b..272dfecb0bf9 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
@@ -222,7 +222,7 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
mHandleView.setAccessibilityDelegate(new HandleViewAccessibilityDelegate());
}
- mMenuViewController = new BubbleBarMenuViewController(mContext, this);
+ mMenuViewController = new BubbleBarMenuViewController(mContext, mHandleView, this);
mMenuViewController.setListener(new BubbleBarMenuViewController.Listener() {
@Override
public void onMenuVisibilityChanged(boolean visible) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
index e781c07f01a7..712e41b0b3c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
@@ -17,17 +17,18 @@ package com.android.wm.shell.bubbles.bar;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.content.Context;
-import android.graphics.Outline;
-import android.graphics.Path;
-import android.graphics.RectF;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewOutlineProvider;
import androidx.annotation.ColorInt;
+import androidx.annotation.VisibleForTesting;
+import androidx.core.animation.IntProperty;
import androidx.core.content.ContextCompat;
import com.android.wm.shell.R;
@@ -37,14 +38,33 @@ import com.android.wm.shell.R;
*/
public class BubbleBarHandleView extends View {
private static final long COLOR_CHANGE_DURATION = 120;
- // Path used to draw the dots
- private final Path mPath = new Path();
+ /** Custom property to set handle color. */
+ private static final IntProperty<BubbleBarHandleView> HANDLE_COLOR = new IntProperty<>(
+ "handleColor") {
+ @Override
+ public void setValue(BubbleBarHandleView bubbleBarHandleView, int color) {
+ bubbleBarHandleView.setHandleColor(color);
+ }
+
+ @Override
+ public Integer get(BubbleBarHandleView bubbleBarHandleView) {
+ return bubbleBarHandleView.getHandleColor();
+ }
+ };
+
+ @VisibleForTesting
+ final Paint mHandlePaint = new Paint();
private final @ColorInt int mHandleLightColor;
private final @ColorInt int mHandleDarkColor;
- private @ColorInt int mCurrentColor;
+ private final ArgbEvaluator mArgbEvaluator = ArgbEvaluator.getInstance();
+ private final float mHandleHeight;
+ private final float mHandleWidth;
+ private float mCurrentHandleHeight;
+ private float mCurrentHandleWidth;
@Nullable
private ObjectAnimator mColorChangeAnim;
+ private @ColorInt int mRegionSamplerColor;
public BubbleBarHandleView(Context context) {
this(context, null /* attrs */);
@@ -61,30 +81,52 @@ public class BubbleBarHandleView extends View {
public BubbleBarHandleView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- final int handleHeight = getResources().getDimensionPixelSize(
+ mHandlePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ mHandlePaint.setStyle(Paint.Style.FILL);
+ mHandlePaint.setColor(0);
+ mHandleHeight = getResources().getDimensionPixelSize(
R.dimen.bubble_bar_expanded_view_handle_height);
+ mHandleWidth = getResources().getDimensionPixelSize(
+ R.dimen.bubble_bar_expanded_view_caption_width);
mHandleLightColor = ContextCompat.getColor(getContext(),
R.color.bubble_bar_expanded_view_handle_light);
mHandleDarkColor = ContextCompat.getColor(getContext(),
R.color.bubble_bar_expanded_view_handle_dark);
-
- setClipToOutline(true);
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- final int handleCenterY = view.getHeight() / 2;
- final int handleTop = handleCenterY - handleHeight / 2;
- final int handleBottom = handleTop + handleHeight;
- final int radius = handleHeight / 2;
- RectF handle = new RectF(/* left = */ 0, handleTop, view.getWidth(), handleBottom);
- mPath.reset();
- mPath.addRoundRect(handle, radius, radius, Path.Direction.CW);
- outline.setPath(mPath);
- }
- });
+ mCurrentHandleHeight = mHandleHeight;
+ mCurrentHandleWidth = mHandleWidth;
setContentDescription(getResources().getString(R.string.handle_text));
}
+ private void setHandleColor(int color) {
+ mHandlePaint.setColor(color);
+ invalidate();
+ }
+
+ private int getHandleColor() {
+ return mHandlePaint.getColor();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ float handleLeft = (getWidth() - mCurrentHandleWidth) / 2;
+ float handleRight = handleLeft + mCurrentHandleWidth;
+ float handleCenterY = (float) getHeight() / 2;
+ float handleTop = (int) (handleCenterY - mCurrentHandleHeight / 2);
+ float handleBottom = handleTop + mCurrentHandleHeight;
+ float cornerRadius = mCurrentHandleHeight / 2;
+ canvas.drawRoundRect(handleLeft, handleTop, handleRight, handleBottom, cornerRadius,
+ cornerRadius, mHandlePaint);
+ }
+
+ /** Sets handle width, height and color. Does not change the layout properties */
+ private void setHandleProperties(float width, float height, int color) {
+ mCurrentHandleHeight = height;
+ mCurrentHandleWidth = width;
+ mHandlePaint.setColor(color);
+ invalidate();
+ }
+
/**
* Updates the handle color.
*
@@ -94,15 +136,15 @@ public class BubbleBarHandleView extends View {
*/
public void updateHandleColor(boolean isRegionDark, boolean animated) {
int newColor = isRegionDark ? mHandleLightColor : mHandleDarkColor;
- if (newColor == mCurrentColor) {
+ if (newColor == mRegionSamplerColor) {
return;
}
+ mRegionSamplerColor = newColor;
if (mColorChangeAnim != null) {
mColorChangeAnim.cancel();
}
- mCurrentColor = newColor;
if (animated) {
- mColorChangeAnim = ObjectAnimator.ofArgb(this, "backgroundColor", newColor);
+ mColorChangeAnim = ObjectAnimator.ofArgb(this, HANDLE_COLOR, newColor);
mColorChangeAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -112,7 +154,39 @@ public class BubbleBarHandleView extends View {
mColorChangeAnim.setDuration(COLOR_CHANGE_DURATION);
mColorChangeAnim.start();
} else {
- setBackgroundColor(newColor);
+ setHandleColor(newColor);
}
}
+
+ /** Returns handle padding top. */
+ public int getHandlePaddingTop() {
+ return (getHeight() - getResources().getDimensionPixelSize(
+ R.dimen.bubble_bar_expanded_view_handle_height)) / 2;
+ }
+
+ /** Animates handle for the bubble menu. */
+ public void animateHandleForMenu(float progress, float widthDelta, float heightDelta,
+ int menuColor) {
+ float currentWidth = mHandleWidth + widthDelta * progress;
+ float currentHeight = mHandleHeight + heightDelta * progress;
+ int color = (int) mArgbEvaluator.evaluate(progress, mRegionSamplerColor, menuColor);
+ setHandleProperties(currentWidth, currentHeight, color);
+ setTranslationY(heightDelta * progress / 2);
+ }
+
+ /** Restores all the properties that were animated to the default values. */
+ public void restoreAnimationDefaults() {
+ setHandleProperties(mHandleWidth, mHandleHeight, mRegionSamplerColor);
+ setTranslationY(0);
+ }
+
+ /** Returns the handle height. */
+ public int getHandleHeight() {
+ return (int) mHandleHeight;
+ }
+
+ /** Returns the handle width. */
+ public int getHandleWidth() {
+ return (int) mHandleWidth;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
index 0ee20ef1731f..99e20097e61c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
@@ -47,6 +47,10 @@ public class BubbleBarMenuView extends LinearLayout {
private ImageView mBubbleIconView;
private ImageView mBubbleDismissIconView;
private TextView mBubbleTitleView;
+ // The animation has three stages. Each stage transition lasts until the animation ends. In
+ // stage 1, the title item content fades in. In stage 2, the background of the option items
+ // fades in. In stage 3, the option item content fades in.
+ private static final int SHOW_MENU_STAGES_COUNT = 3;
public BubbleBarMenuView(Context context) {
this(context, null /* attrs */);
@@ -97,6 +101,35 @@ public class BubbleBarMenuView extends LinearLayout {
}
}
+ /** Animates the menu from the specified start scale. */
+ public void animateFromStartScale(float currentScale, float progress) {
+ int menuItemElevation = getResources().getDimensionPixelSize(
+ R.dimen.bubble_manage_menu_elevation);
+ setScaleX(currentScale);
+ setScaleY(currentScale);
+ setAlphaForTitleViews(progress);
+ mBubbleSectionView.setElevation(menuItemElevation * progress);
+ float actionsBackgroundAlpha = Math.max(0,
+ (progress - (float) 1 / SHOW_MENU_STAGES_COUNT) * (SHOW_MENU_STAGES_COUNT - 1));
+ float actionItemsAlpha = Math.max(0,
+ (progress - (float) 2 / SHOW_MENU_STAGES_COUNT) * SHOW_MENU_STAGES_COUNT);
+ mActionsSectionView.setAlpha(actionsBackgroundAlpha);
+ mActionsSectionView.setElevation(menuItemElevation * actionsBackgroundAlpha);
+ setMenuItemViewsAlpha(actionItemsAlpha);
+ }
+
+ private void setAlphaForTitleViews(float alpha) {
+ mBubbleIconView.setAlpha(alpha);
+ mBubbleTitleView.setAlpha(alpha);
+ mBubbleDismissIconView.setAlpha(alpha);
+ }
+
+ private void setMenuItemViewsAlpha(float alpha) {
+ for (int i = mActionsSectionView.getChildCount() - 1; i >= 0; i--) {
+ mActionsSectionView.getChildAt(i).setAlpha(alpha);
+ }
+ }
+
/** Update menu details with bubble info */
void updateInfo(Bubble bubble) {
if (bubble.getIcon() != null) {
@@ -153,6 +186,11 @@ public class BubbleBarMenuView extends LinearLayout {
return mBubbleSectionView.getAlpha();
}
+ /** Return title menu item height. */
+ public float getTitleItemHeight() {
+ return mBubbleSectionView.getHeight();
+ }
+
/**
* Menu action details used to create menu items
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
index 514810745e10..9dd0cae20370 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
@@ -15,6 +15,9 @@
*/
package com.android.wm.shell.bubbles.bar;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -26,13 +29,10 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import androidx.dynamicanimation.animation.DynamicAnimation;
-import androidx.dynamicanimation.animation.SpringForce;
-
+import com.android.app.animation.Interpolators;
import com.android.wm.shell.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.Bubble;
-import com.android.wm.shell.shared.animation.PhysicsAnimator;
import java.util.ArrayList;
@@ -40,22 +40,26 @@ import java.util.ArrayList;
* Manages bubble bar expanded view menu presentation and animations
*/
class BubbleBarMenuViewController {
- private static final float MENU_INITIAL_SCALE = 0.5f;
+
+ private static final float WIDTH_SWAP_FRACTION = 0.4F;
+ private static final long MENU_ANIMATION_DURATION = 600;
+
private final Context mContext;
private final ViewGroup mRootView;
+ private final BubbleBarHandleView mHandleView;
private @Nullable Listener mListener;
private @Nullable Bubble mBubble;
private @Nullable BubbleBarMenuView mMenuView;
/** A transparent view used to intercept touches to collapse menu when presented */
private @Nullable View mScrimView;
- private @Nullable PhysicsAnimator<BubbleBarMenuView> mMenuAnimator;
- private PhysicsAnimator.SpringConfig mMenuSpringConfig;
+ private @Nullable ValueAnimator mMenuAnimator;
+
- BubbleBarMenuViewController(Context context, ViewGroup rootView) {
+ BubbleBarMenuViewController(Context context, BubbleBarHandleView handleView,
+ ViewGroup rootView) {
mContext = context;
mRootView = rootView;
- mMenuSpringConfig = new PhysicsAnimator.SpringConfig(
- SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+ mHandleView = handleView;
}
/** Tells if the menu is visible or being animated */
@@ -81,20 +85,21 @@ class BubbleBarMenuViewController {
if (mMenuView == null || mScrimView == null) {
setupMenu();
}
- cancelAnimations();
- mMenuView.setVisibility(View.VISIBLE);
- mScrimView.setVisibility(View.VISIBLE);
- Runnable endActions = () -> {
- mMenuView.getChildAt(0).requestAccessibilityFocus();
- if (mListener != null) {
- mListener.onMenuVisibilityChanged(true /* isShown */);
+ runOnMenuIsMeasured(() -> {
+ mMenuView.setVisibility(View.VISIBLE);
+ mScrimView.setVisibility(View.VISIBLE);
+ Runnable endActions = () -> {
+ mMenuView.getChildAt(0).requestAccessibilityFocus();
+ if (mListener != null) {
+ mListener.onMenuVisibilityChanged(true /* isShown */);
+ }
+ };
+ if (animated) {
+ animateTransition(true /* show */, endActions);
+ } else {
+ endActions.run();
}
- };
- if (animated) {
- animateTransition(true /* show */, endActions);
- } else {
- endActions.run();
- }
+ });
}
/**
@@ -103,18 +108,30 @@ class BubbleBarMenuViewController {
*/
void hideMenu(boolean animated) {
if (mMenuView == null || mScrimView == null) return;
- cancelAnimations();
- Runnable endActions = () -> {
- mMenuView.setVisibility(View.GONE);
- mScrimView.setVisibility(View.GONE);
- if (mListener != null) {
- mListener.onMenuVisibilityChanged(false /* isShown */);
+ runOnMenuIsMeasured(() -> {
+ Runnable endActions = () -> {
+ mHandleView.restoreAnimationDefaults();
+ mMenuView.setVisibility(View.GONE);
+ mScrimView.setVisibility(View.GONE);
+ mHandleView.setVisibility(View.VISIBLE);
+ if (mListener != null) {
+ mListener.onMenuVisibilityChanged(false /* isShown */);
+ }
+ };
+ if (animated) {
+ animateTransition(false /* show */, endActions);
+ } else {
+ endActions.run();
}
- };
- if (animated) {
- animateTransition(false /* show */, endActions);
+ });
+ }
+
+ private void runOnMenuIsMeasured(Runnable action) {
+ if (mMenuView.getWidth() == 0 || mMenuView.getHeight() == 0) {
+ // the menu view is not yet measured, postpone showing the animation
+ mMenuView.post(() -> runOnMenuIsMeasured(action));
} else {
- endActions.run();
+ action.run();
}
}
@@ -125,24 +142,63 @@ class BubbleBarMenuViewController {
*/
private void animateTransition(boolean show, Runnable endActions) {
if (mMenuView == null) return;
- mMenuAnimator = PhysicsAnimator.getInstance(mMenuView);
- mMenuAnimator.setDefaultSpringConfig(mMenuSpringConfig);
- mMenuAnimator
- .spring(DynamicAnimation.ALPHA, show ? 1f : 0f)
- .spring(DynamicAnimation.SCALE_Y, show ? 1f : MENU_INITIAL_SCALE)
- .withEndActions(() -> {
- mMenuAnimator = null;
- endActions.run();
- })
- .start();
+ float startValue = show ? 0 : 1;
+ if (mMenuAnimator != null && mMenuAnimator.isRunning()) {
+ startValue = (float) mMenuAnimator.getAnimatedValue();
+ mMenuAnimator.cancel();
+ }
+ ValueAnimator showMenuAnimation = ValueAnimator.ofFloat(startValue, show ? 1 : 0);
+ showMenuAnimation.setDuration(MENU_ANIMATION_DURATION);
+ showMenuAnimation.setInterpolator(Interpolators.EMPHASIZED);
+ showMenuAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mMenuAnimator = null;
+ endActions.run();
+ }
+ });
+ mMenuAnimator = showMenuAnimation;
+ setupAnimatorListener(showMenuAnimation);
+ showMenuAnimation.start();
}
- /** Cancel running animations */
- private void cancelAnimations() {
- if (mMenuAnimator != null) {
- mMenuAnimator.cancel();
- mMenuAnimator = null;
+ /** Setup listener that orchestrates the animation. */
+ private void setupAnimatorListener(ValueAnimator showMenuAnimation) {
+ // Getting views properties start values
+ int widthDiff = mMenuView.getWidth() - mHandleView.getHandleWidth();
+ int handleHeight = mHandleView.getHandleHeight();
+ float targetWidth = mHandleView.getHandleWidth() + widthDiff * WIDTH_SWAP_FRACTION;
+ float targetHeight = targetWidth * mMenuView.getTitleItemHeight() / mMenuView.getWidth();
+ int menuColor;
+ try (TypedArray ta = mContext.obtainStyledAttributes(new int[]{
+ com.android.internal.R.attr.materialColorSurfaceBright,
+ })) {
+ menuColor = ta.getColor(0, Color.WHITE);
}
+ // Calculating deltas
+ float swapScale = targetWidth / mMenuView.getWidth();
+ float handleWidthDelta = targetWidth - mHandleView.getHandleWidth();
+ float handleHeightDelta = targetHeight - handleHeight;
+ // Setting update listener that will orchestrate the animation
+ showMenuAnimation.addUpdateListener(animator -> {
+ float animationProgress = (float) animator.getAnimatedValue();
+ boolean showHandle = animationProgress <= WIDTH_SWAP_FRACTION;
+ mHandleView.setVisibility(showHandle ? View.VISIBLE : View.GONE);
+ mMenuView.setVisibility(showHandle ? View.GONE : View.VISIBLE);
+ if (showHandle) {
+ float handleAnimationProgress = animationProgress / WIDTH_SWAP_FRACTION;
+ mHandleView.animateHandleForMenu(handleAnimationProgress, handleWidthDelta,
+ handleHeightDelta, menuColor);
+ } else {
+ mMenuView.setTranslationY(mHandleView.getHandlePaddingTop());
+ mMenuView.setPivotY(0);
+ mMenuView.setPivotX((float) mMenuView.getWidth() / 2);
+ float menuAnimationProgress =
+ (animationProgress - WIDTH_SWAP_FRACTION) / (1 - WIDTH_SWAP_FRACTION);
+ float currentMenuScale = swapScale + (1 - swapScale) * menuAnimationProgress;
+ mMenuView.animateFromStartScale(currentMenuScale, menuAnimationProgress);
+ }
+ });
}
/** Sets up and inflate menu views */
@@ -150,9 +206,6 @@ class BubbleBarMenuViewController {
// Menu view setup
mMenuView = (BubbleBarMenuView) LayoutInflater.from(mContext).inflate(
R.layout.bubble_bar_menu_view, mRootView, false);
- mMenuView.setAlpha(0f);
- mMenuView.setPivotY(0f);
- mMenuView.setScaleY(MENU_INITIAL_SCALE);
mMenuView.setOnCloseListener(() -> hideMenu(true /* animated */));
if (mBubble != null) {
mMenuView.updateInfo(mBubble);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java
index d38b848fbb4d..329a10998f23 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java
@@ -16,9 +16,8 @@
package com.android.wm.shell.bubbles.bar;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
-import android.graphics.drawable.ColorDrawable;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -47,10 +46,9 @@ public class BubbleBarHandleViewTest extends ShellTestCase {
public void testUpdateHandleColor_lightBg() {
mHandleView.updateHandleColor(false /* isRegionDark */, false /* animated */);
- assertTrue(mHandleView.getClipToOutline());
- assertTrue(mHandleView.getBackground() instanceof ColorDrawable);
- ColorDrawable bgDrawable = (ColorDrawable) mHandleView.getBackground();
- assertEquals(bgDrawable.getColor(),
+ assertFalse(mHandleView.getClipToOutline());
+ int handleColor = mHandleView.mHandlePaint.getColor();
+ assertEquals(handleColor,
ContextCompat.getColor(mContext, R.color.bubble_bar_expanded_view_handle_dark));
}
@@ -58,10 +56,9 @@ public class BubbleBarHandleViewTest extends ShellTestCase {
public void testUpdateHandleColor_darkBg() {
mHandleView.updateHandleColor(true /* isRegionDark */, false /* animated */);
- assertTrue(mHandleView.getClipToOutline());
- assertTrue(mHandleView.getBackground() instanceof ColorDrawable);
- ColorDrawable bgDrawable = (ColorDrawable) mHandleView.getBackground();
- assertEquals(bgDrawable.getColor(),
+ assertFalse(mHandleView.getClipToOutline());
+ int handleColor = mHandleView.mHandlePaint.getColor();
+ assertEquals(handleColor,
ContextCompat.getColor(mContext, R.color.bubble_bar_expanded_view_handle_light));
}
}