Animate overflow button
Add overflow button to mBubbleContainer
Update animation math to account for 6th child
Bug: 138116789
Fixes: 148233216
Test: manual: expand stack - button animates like normal bubbles
Test: manual: collapse stack - button animates like normal bubbles
Test: atest SystemUITests
Change-Id: I8bd575a116ab4a7443c2d682debc5c5207df1808
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index ac06f95..e954163 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -866,10 +866,6 @@
mOverflowCallback.run();
}
- if (update.addedBubble != null) {
- mStackView.addBubble(update.addedBubble);
- }
-
// Collapsing? Do this first before remaining steps.
if (update.expandedChanged && !update.expanded) {
mStackView.setExpanded(false);
@@ -916,6 +912,10 @@
}
}
+ if (update.addedBubble != null) {
+ mStackView.addBubble(update.addedBubble);
+ }
+
if (update.updatedBubble != null) {
mStackView.updateBubble(update.updatedBubble);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 685bb94..6062a3d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -526,8 +526,13 @@
R.layout.bubble_expanded_view, this /* root */, false /* attachToRoot */);
mOverflowExpandedView.setOverflow(true);
- mInflater.inflate(R.layout.bubble_overflow_button, this);
- mOverflowBtn = findViewById(R.id.bubble_overflow_button);
+ mOverflowBtn = (ImageView) mInflater.inflate(R.layout.bubble_overflow_button,
+ this /* root */,
+ false /* attachToRoot */);
+
+ mBubbleContainer.addView(mOverflowBtn, 0,
+ new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
+
mOverflowBtn.setOnClickListener(v -> {
setSelectedBubble(null);
});
@@ -541,11 +546,13 @@
ColorDrawable bg = new ColorDrawable(bgColor);
AdaptiveIconDrawable adaptiveIcon = new AdaptiveIconDrawable(bg, fg);
mOverflowBtn.setImageDrawable(adaptiveIcon);
+
mOverflowBtn.setVisibility(GONE);
}
void showExpandedViewContents(int displayId) {
- if (mOverflowExpandedView.getVirtualDisplayId() == displayId) {
+ if (mOverflowExpandedView != null
+ && mOverflowExpandedView.getVirtualDisplayId() == displayId) {
mOverflowExpandedView.setContentVisibility(true);
} else if (mExpandedBubble != null
&& mExpandedBubble.getExpandedView().getVirtualDisplayId() == displayId) {
@@ -714,7 +721,7 @@
private void updateSystemGestureExcludeRects() {
// Exclude the region occupied by the first BubbleView in the stack
Rect excludeZone = mSystemGestureExclusionRects.get(0);
- if (mBubbleContainer.getChildCount() > 0) {
+ if (getBubbleCount() > 0) {
View firstBubble = mBubbleContainer.getChildAt(0);
excludeZone.set(firstBubble.getLeft(), firstBubble.getTop(), firstBubble.getRight(),
firstBubble.getBottom());
@@ -775,7 +782,7 @@
Log.d(TAG, "addBubble: " + bubble);
}
- if (mBubbleContainer.getChildCount() == 0) {
+ if (getBubbleCount() == 0) {
mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
}
@@ -817,16 +824,13 @@
}
if (mIsExpanded) {
if (DEBUG_BUBBLE_STACK_VIEW) {
- Log.d(TAG, "Expanded && overflow > 0. Show overflow button at");
- Log.d(TAG, "x: " + mExpandedAnimationController.getOverflowBtnLeft());
- Log.d(TAG, "y: " + mExpandedAnimationController.getExpandedY());
+ Log.d(TAG, "Show overflow button.");
}
- mOverflowBtn.setX(mExpandedAnimationController.getOverflowBtnLeft());
- mOverflowBtn.setY(mExpandedAnimationController.getExpandedY());
mOverflowBtn.setVisibility(VISIBLE);
- mExpandedAnimationController.setShowOverflowBtn(true);
if (apply) {
- mExpandedAnimationController.expandFromStack(null /* after */);
+ mExpandedAnimationController.expandFromStack(() -> {
+ updatePointerPosition();
+ } /* after */);
}
} else {
if (DEBUG_BUBBLE_STACK_VIEW) {
@@ -947,7 +951,7 @@
if (mIsExpanded) {
if (isIntersecting(mBubbleContainer, x, y)) {
// Could be tapping or dragging a bubble while expanded
- for (int i = 0; i < mBubbleContainer.getChildCount(); i++) {
+ for (int i = 0; i < getBubbleCount(); i++) {
BadgedImageView view = (BadgedImageView) mBubbleContainer.getChildAt(i);
if (isIntersecting(view, x, y)) {
return view;
@@ -1103,7 +1107,7 @@
/** Return the BubbleView at the given index from the bubble container. */
public BadgedImageView getBubbleAt(int i) {
- return mBubbleContainer.getChildCount() > i
+ return getBubbleCount() > i
? (BadgedImageView) mBubbleContainer.getChildAt(i)
: null;
}
@@ -1567,7 +1571,7 @@
return;
}
if (!mIsExpanded) {
- if (mBubbleContainer.getChildCount() > 0) {
+ if (getBubbleCount() > 0) {
mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect);
}
// Increase the touch target size of the bubble
@@ -1661,7 +1665,7 @@
/** Sets the appropriate Z-order and dot position for each bubble in the stack. */
private void updateBubbleZOrdersAndDotPosition(boolean animate) {
- int bubbleCount = mBubbleContainer.getChildCount();
+ int bubbleCount = getBubbleCount();
for (int i = 0; i < bubbleCount; i++) {
BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i);
bv.setZ((mMaxBubbles * mBubbleElevation) - i);
@@ -1677,30 +1681,23 @@
if (expandedBubble == null) {
return;
}
-
int index = getBubbleIndex(expandedBubble);
- if (index >= mMaxBubbles) {
- // In between state, where extra bubble will be overflowed, and new bubble added
- index = 0;
- }
float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index);
float halfBubble = mBubbleSize / 2f;
float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble;
// Padding might be adjusted for insets, so get it directly from the view
bubbleCenter -= mExpandedViewContainer.getPaddingLeft();
-
- if (index >= mMaxBubbles) {
- Bubble first = mBubbleData.getBubbles().get(0);
- first.getExpandedView().setPointerPosition(bubbleCenter);
- } else {
- expandedBubble.getExpandedView().setPointerPosition(bubbleCenter);
- }
+ expandedBubble.getExpandedView().setPointerPosition(bubbleCenter);
}
/**
* @return the number of bubbles in the stack view.
*/
public int getBubbleCount() {
+ if (BubbleExperimentConfig.allowBubbleOverflow(mContext)) {
+ // Subtract 1 for the overflow button which is always in the bubble container.
+ return mBubbleContainer.getChildCount() - 1;
+ }
return mBubbleContainer.getChildCount();
}
@@ -1797,7 +1794,7 @@
/** For debugging only */
List<Bubble> getBubblesOnScreen() {
List<Bubble> bubbles = new ArrayList<>();
- for (int i = 0; i < mBubbleContainer.getChildCount(); i++) {
+ for (int i = 0; i < getBubbleCount(); i++) {
View child = mBubbleContainer.getChildAt(i);
if (child instanceof BadgedImageView) {
String key = ((BadgedImageView) child).getKey();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 6d6969d..aa549dc 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -31,6 +31,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.bubbles.BubbleExperimentConfig;
import com.google.android.collect.Sets;
@@ -67,13 +68,13 @@
private float mBubblePaddingTop;
/** Size of each bubble. */
private float mBubbleSizePx;
- /** Width of the overflow button. */
- private float mOverflowBtnWidth;
+ /** Space between bubbles in row above expanded view. */
+ private float mSpaceBetweenBubbles;
/** Height of the status bar. */
private float mStatusBarHeight;
/** Size of display. */
private Point mDisplaySize;
- /** Max number of bubbles shown in row above expanded view.*/
+ /** Max number of bubbles shown in row above expanded view. */
private int mBubblesMaxRendered;
/** What the current screen orientation is. */
private int mScreenOrientation;
@@ -99,7 +100,6 @@
private boolean mSpringingBubbleToTouch = false;
private int mExpandedViewPadding;
- private boolean mShowOverflowBtn;
public ExpandedAnimationController(Point displaySize, int expandedViewPadding,
int orientation) {
@@ -153,14 +153,6 @@
}
}
- public void setShowOverflowBtn(boolean showBtn) {
- mShowOverflowBtn = showBtn;
- }
-
- public boolean getShowOverflowBtn() {
- return mShowOverflowBtn;
- }
-
/**
* Animates the bubbles along a curved path, either to expand them along the top or collapse
* them back into a stack.
@@ -369,10 +361,10 @@
}
final WindowInsets insets = mLayout.getRootWindowInsets();
return mBubblePaddingTop + Math.max(
- mStatusBarHeight,
- insets.getDisplayCutout() != null
- ? insets.getDisplayCutout().getSafeInsetTop()
- : 0);
+ mStatusBarHeight,
+ insets.getDisplayCutout() != null
+ ? insets.getDisplayCutout().getSafeInsetTop()
+ : 0);
}
/** Description of current animation controller state. */
@@ -391,11 +383,15 @@
mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
- mOverflowBtnWidth = mBubbleSizePx;
mStatusBarHeight =
res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
+ // Includes overflow button.
+ float totalGapWidth = getWidthForDisplayingBubbles() - (mExpandedViewPadding * 2)
+ - (mBubblesMaxRendered + 1) * mBubbleSizePx;
+ mSpaceBetweenBubbles = totalGapWidth / mBubblesMaxRendered;
+
// Ensure that all child views are at 1x scale, and visible, in case they were animating
// in.
mLayout.setVisibility(View.VISIBLE);
@@ -506,18 +502,10 @@
* @return Bubble left x from left edge of screen.
*/
public float getBubbleLeft(int index) {
- final float bubbleFromRowLeft = index * (mBubbleSizePx + getSpaceBetweenBubbles());
+ final float bubbleFromRowLeft = index * (mBubbleSizePx + mSpaceBetweenBubbles);
return getRowLeft() + bubbleFromRowLeft;
}
- public float getOverflowBtnLeft() {
- if (mLayout == null || mLayout.getChildCount() == 0) {
- return 0;
- }
- return getBubbleLeft(mLayout.getChildCount() - 1) + mBubbleSizePx
- + getSpaceBetweenBubbles();
- }
-
/**
* When expanded, the bubbles are centered in the screen. In portrait, all available space is
* used. In landscape we have too much space so the value is restricted. This method accounts
@@ -539,7 +527,7 @@
* Determines the available screen width without the cutout.
*
* @param subtractStableInsets Whether or not stable insets should also be removed from the
- * returned width.
+ * returned width.
* @return the total screen width available accounting for cutouts and insets,
* iff {@param includeStableInsets} is true.
*/
@@ -566,38 +554,13 @@
if (mLayout == null) {
return 0;
}
-
- int bubbleCount = mLayout.getChildCount();
-
- final float totalBubbleWidth = bubbleCount * mBubbleSizePx;
- final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles();
- float rowWidth = totalGapWidth + totalBubbleWidth;
- if (mShowOverflowBtn) {
- rowWidth += getSpaceBetweenBubbles();
- rowWidth += mOverflowBtnWidth;
- }
+ float rowWidth = (mLayout.getChildCount() * mBubbleSizePx)
+ + ((mLayout.getChildCount() - 1) * mSpaceBetweenBubbles);
// This display size we're using includes the size of the insets, we want the true
// center of the display minus the notch here, which means we should include the
// stable insets (e.g. status bar, nav bar) in this calculation.
final float trueCenter = getAvailableScreenWidth(false /* subtractStableInsets */) / 2f;
- final float halfRow = rowWidth / 2f;
- final float rowLeft = trueCenter - halfRow;
- return rowLeft;
- }
-
- /**
- * @return Space between bubbles in row above expanded view.
- */
- private float getSpaceBetweenBubbles() {
- final float totalBubbleWidth = mBubblesMaxRendered * mBubbleSizePx;
- final float rowMargins = mExpandedViewPadding * 2;
- float totalGapWidth = getWidthForDisplayingBubbles() - rowMargins - totalBubbleWidth;
- if (mShowOverflowBtn) {
- totalGapWidth -= mBubbleSizePx;
- }
- final int gapCount = mBubblesMaxRendered - 1;
- final float gapWidth = totalGapWidth / gapCount;
- return gapWidth;
+ return trueCenter - (rowWidth / 2f);
}
}