From d25c65f9f2ccdafd8d95d2c2d16b55d0c55be599 Mon Sep 17 00:00:00 2001 From: mpodolian Date: Mon, 15 Apr 2024 16:57:01 +0100 Subject: [PATCH] Update bubble bar to match visual spec Made bubble bar icon size adjustable and listen to the task bar icon size changes. Additionally fixes an issue where the pointer arrow could be misplaced. Test: BubbleBarViewAnimatorTest.kt Flag: ACONFIG com.android.wm.shell.enable_bubble_bar DEVELOPMENT Bug: 295027436 Fixes: 334781761 Change-Id: Ie4ceee84cc00baa0186a3d5b431080c8495c7285 --- quickstep/res/values/dimens.xml | 9 ++- .../taskbar/bubbles/BubbleBarBackground.kt | 6 +- .../taskbar/bubbles/BubbleBarView.java | 68 +++++++++++++++---- .../bubbles/BubbleBarViewController.java | 50 ++++++++++---- 4 files changed, 103 insertions(+), 30 deletions(-) diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 69e07f24cb..dc28614cdc 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -427,11 +427,14 @@ 2dp 90dp - 50dp + 32dp + 36dp 24dp 12dp - 24dp - 3dp + 16dp + 6dp + 8dp + 12dp 1dp diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt index 8eeb0550ae..979934904d 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt @@ -31,7 +31,7 @@ import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound import com.android.wm.shell.common.TriangleShape /** Drawable for the background of the bubble bar. */ -class BubbleBarBackground(context: Context, private val backgroundHeight: Float) : Drawable() { +class BubbleBarBackground(context: Context, private var backgroundHeight: Float) : Drawable() { private val DARK_THEME_SHADOW_ALPHA = 51f private val LIGHT_THEME_SHADOW_ALPHA = 25f @@ -171,4 +171,8 @@ class BubbleBarBackground(context: Context, private val backgroundHeight: Float) fun setArrowAlpha(alpha: Int) { arrowDrawable.paint.alpha = alpha } + + fun setHeight(newHeight: Float) { + backgroundHeight = newHeight + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java index 711ba6258f..1003c3f8e0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java @@ -106,10 +106,12 @@ public class BubbleBarView extends FrameLayout { private final Rect mBubbleBarBounds = new Rect(); // The amount the bubbles overlap when they are stacked in the bubble bar private final float mIconOverlapAmount; - // The spacing between the bubbles when they are expanded in the bubble bar - private final float mIconSpacing; + // The spacing between the bubbles when bubble bar is expanded + private final float mExpandedBarIconsSpacing; + // The spacing between the bubbles and the borders of the bubble bar + private float mBubbleBarPadding; // The size of a bubble in the bar - private final float mIconSize; + private float mIconSize; // The elevation of the bubbles within the bar private final float mBubbleElevation; private final float mDragElevation; @@ -169,16 +171,17 @@ public class BubbleBarView extends FrameLayout { setAlpha(0); setVisibility(INVISIBLE); mIconOverlapAmount = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_overlap); - mIconSpacing = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_spacing); + mBubbleBarPadding = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_spacing); mIconSize = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size); + mExpandedBarIconsSpacing = getResources().getDimensionPixelSize( + R.dimen.bubblebar_expanded_icon_spacing); mBubbleElevation = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_elevation); mDragElevation = getResources().getDimensionPixelSize(R.dimen.bubblebar_drag_elevation); mPointerSize = getResources().getDimensionPixelSize(R.dimen.bubblebar_pointer_size); setClipToPadding(false); - mBubbleBarBackground = new BubbleBarBackground(context, - getResources().getDimensionPixelSize(R.dimen.bubblebar_size)); + mBubbleBarBackground = new BubbleBarBackground(context, getBubbleBarHeight()); setBackgroundDrawable(mBubbleBarBackground); mWidthAnimator.setDuration(WIDTH_ANIMATION_DURATION_MS); @@ -219,6 +222,29 @@ public class BubbleBarView extends FrameLayout { }); } + /** + * Sets new icon size and spacing between icons and bubble bar borders. + * + * @param newIconSize new icon size + * @param spacing spacing between icons and bubble bar borders. + */ + // TODO(b/335575529): animate bubble bar icons size change + public void setIconSizeAndPadding(float newIconSize, float spacing) { + // TODO(b/335457839): handle new bubble animation during the size change + mBubbleBarPadding = spacing; + mIconSize = newIconSize; + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View childView = getChildAt(i); + FrameLayout.LayoutParams params = (LayoutParams) childView.getLayoutParams(); + params.height = (int) mIconSize; + params.width = (int) mIconSize; + childView.setLayoutParams(params); + } + mBubbleBarBackground.setHeight(getBubbleBarHeight()); + updateLayoutParams(); + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); @@ -516,6 +542,13 @@ public class BubbleBarView extends FrameLayout { setLayoutParams(lp); } + private void updateLayoutParams() { + LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); + lp.height = getBubbleBarHeight(); + lp.width = (int) (mIsBarExpanded ? expandedWidth() : collapsedWidth()); + setLayoutParams(lp); + } + /** @return the horizontal margin between the bubble bar and the edge of the screen. */ int getHorizontalMargin() { LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); @@ -551,12 +584,12 @@ public class BubbleBarView extends FrameLayout { final float collapsedX; if (onLeft) { // If bar is on the left, bubbles are ordered right to left - expandedX = (bubbleCount - i - 1) * (mIconSize + mIconSpacing); + expandedX = (bubbleCount - i - 1) * (mIconSize + mExpandedBarIconsSpacing); // Shift the first bubble only if there are more bubbles in addition to overflow collapsedX = i == 0 && bubbleCount > 2 ? mIconOverlapAmount : 0; } else { // Bubbles ordered left to right, don't move the first bubble - expandedX = i * (mIconSize + mIconSpacing); + expandedX = i * (mIconSize + mExpandedBarIconsSpacing); collapsedX = i == 0 ? 0 : mIconOverlapAmount; } @@ -599,14 +632,14 @@ public class BubbleBarView extends FrameLayout { final float interpolatedWidth = widthState * (expandedWidth - collapsedWidth) + collapsedWidth; final float arrowPosition; + + float interpolatedShift = (expandedArrowPosition - collapsedArrowPosition) * widthState; if (onLeft) { - float interpolatedShift = (expandedArrowPosition - collapsedArrowPosition) * widthState; arrowPosition = collapsedArrowPosition + interpolatedShift; } else { if (mIsBarExpanded) { - // when the bar is expanding, the selected bubble is always the first, so the arrow - // always shifts with the interpolated width. - arrowPosition = currentWidth - interpolatedWidth + collapsedArrowPosition; + arrowPosition = currentWidth - interpolatedWidth + collapsedArrowPosition + + interpolatedShift; } else { final float targetPosition = currentWidth - collapsedWidth + collapsedArrowPosition; arrowPosition = @@ -709,7 +742,8 @@ public class BubbleBarView extends FrameLayout { } else { bubblePosition = index; } - return getPaddingStart() + bubblePosition * (mIconSize + mIconSpacing) + mIconSize / 2f; + return getPaddingStart() + bubblePosition * (mIconSize + mExpandedBarIconsSpacing) + + mIconSize / 2f; } private float arrowPositionForSelectedWhenCollapsed() { @@ -770,7 +804,9 @@ public class BubbleBarView extends FrameLayout { public float expandedWidth() { final int childCount = getChildCount(); final int horizontalPadding = getPaddingStart() + getPaddingEnd(); - return childCount * (mIconSize + mIconSpacing) + horizontalPadding; + // spaces amount is less than child count by 1, or 0 if no child views + int spacesCount = Math.max(childCount - 1, 0); + return childCount * mIconSize + spacesCount * mExpandedBarIconsSpacing + horizontalPadding; } private float collapsedWidth() { @@ -783,6 +819,10 @@ public class BubbleBarView extends FrameLayout { : mIconSize + horizontalPadding; } + private int getBubbleBarHeight() { + return (int) (mIconSize + mBubbleBarPadding * 2 + mPointerSize); + } + /** * Returns whether the given MotionEvent, *in screen coordinates*, is within bubble bar * touch bounds. diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java index aa1b4dfb40..e3cdd09686 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java @@ -18,9 +18,12 @@ package com.android.launcher3.taskbar.bubbles; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; +import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; +import android.util.DisplayMetrics; import android.util.Log; +import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -52,12 +55,13 @@ import java.util.function.Consumer; public class BubbleBarViewController { private static final String TAG = BubbleBarViewController.class.getSimpleName(); - + private static final float APP_ICON_SMALL_DP = 44f; + private static final float APP_ICON_MEDIUM_DP = 48f; + private static final float APP_ICON_LARGE_DP = 52f; private final SystemUiProxy mSystemUiProxy; private final TaskbarActivityContext mActivity; private final BubbleBarView mBarView; - private final int mIconSize; - private final int mPointerSize; + private int mIconSize; // Initialized in init. private BubbleStashController mBubbleStashController; @@ -96,9 +100,8 @@ public class BubbleBarViewController { mSystemUiProxy = SystemUiProxy.INSTANCE.get(mActivity); mBubbleBarAlpha = new MultiValueAlpha(mBarView, 1 /* num alpha channels */); mBubbleBarAlpha.setUpdateVisibility(true); - mIconSize = activity.getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size); - mPointerSize = activity.getResources().getDimensionPixelSize( - R.dimen.bubblebar_pointer_size); + mIconSize = activity.getResources().getDimensionPixelSize( + R.dimen.bubblebar_icon_size); } public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) { @@ -108,12 +111,8 @@ public class BubbleBarViewController { mTaskbarStashController = controllers.taskbarStashController; mTaskbarInsetsController = controllers.taskbarInsetsController; - mActivity.addOnDeviceProfileChangeListener(dp -> - mBarView.getLayoutParams().height = - mActivity.getDeviceProfile().taskbarHeight + mPointerSize - ); - mBarView.getLayoutParams().height = - mActivity.getDeviceProfile().taskbarHeight + mPointerSize; + mActivity.addOnDeviceProfileChangeListener(dp -> setBubbleBarIconSize(dp.taskbarIconSize)); + setBubbleBarIconSize(mActivity.getDeviceProfile().taskbarIconSize); mBubbleBarScale.updateValue(1f); mBubbleClickListener = v -> onBubbleClicked(v); mBubbleBarClickListener = v -> onBubbleBarClicked(); @@ -260,6 +259,33 @@ public class BubbleBarViewController { } } + private void setBubbleBarIconSize(int newIconSize) { + if (newIconSize == mIconSize) { + return; + } + Resources res = mActivity.getResources(); + DisplayMetrics dm = res.getDisplayMetrics(); + float smallIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + APP_ICON_SMALL_DP, dm); + float mediumIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + APP_ICON_MEDIUM_DP, dm); + float largeIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + APP_ICON_LARGE_DP, dm); + float smallMediumThreshold = (smallIconSize + mediumIconSize) / 2f; + float mediumLargeThreshold = (mediumIconSize + largeIconSize) / 2f; + mIconSize = newIconSize <= smallMediumThreshold + ? res.getDimensionPixelSize(R.dimen.bubblebar_icon_size_small) : + res.getDimensionPixelSize(R.dimen.bubblebar_icon_size); + float bubbleBarPadding = newIconSize >= mediumLargeThreshold + ? res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing_large) : + res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing); + + mBarView.setIconSizeAndPadding(mIconSize, bubbleBarPadding); + mBarView.setPadding((int) bubbleBarPadding, mBarView.getPaddingTop(), + (int) bubbleBarPadding, + mBarView.getPaddingBottom()); + } + /** Sets a callback that updates the selected bubble after the bubble bar collapses. */ public void setUpdateSelectedBubbleAfterCollapse( Consumer updateSelectedBubbleAfterCollapse) {