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
This commit is contained in:
@@ -866,10 +866,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
||||
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 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
||||
}
|
||||
}
|
||||
|
||||
if (update.addedBubble != null) {
|
||||
mStackView.addBubble(update.addedBubble);
|
||||
}
|
||||
|
||||
if (update.updatedBubble != null) {
|
||||
mStackView.updateBubble(update.updatedBubble);
|
||||
}
|
||||
|
||||
@@ -526,8 +526,13 @@ public class BubbleStackView extends FrameLayout {
|
||||
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 @@ public class BubbleStackView extends FrameLayout {
|
||||
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 @@ public class BubbleStackView extends FrameLayout {
|
||||
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 @@ public class BubbleStackView extends FrameLayout {
|
||||
Log.d(TAG, "addBubble: " + bubble);
|
||||
}
|
||||
|
||||
if (mBubbleContainer.getChildCount() == 0) {
|
||||
if (getBubbleCount() == 0) {
|
||||
mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
|
||||
}
|
||||
|
||||
@@ -817,16 +824,13 @@ public class BubbleStackView extends FrameLayout {
|
||||
}
|
||||
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 @@ public class BubbleStackView extends FrameLayout {
|
||||
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 @@ public class BubbleStackView extends FrameLayout {
|
||||
|
||||
/** 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 @@ public class BubbleStackView extends FrameLayout {
|
||||
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 @@ public class BubbleStackView extends FrameLayout {
|
||||
|
||||
/** 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 @@ public class BubbleStackView extends FrameLayout {
|
||||
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 @@ public class BubbleStackView extends FrameLayout {
|
||||
/** 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();
|
||||
|
||||
@@ -31,6 +31,7 @@ import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
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 @@ public class ExpandedAnimationController
|
||||
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 @@ public class ExpandedAnimationController
|
||||
private boolean mSpringingBubbleToTouch = false;
|
||||
|
||||
private int mExpandedViewPadding;
|
||||
private boolean mShowOverflowBtn;
|
||||
|
||||
public ExpandedAnimationController(Point displaySize, int expandedViewPadding,
|
||||
int orientation) {
|
||||
@@ -153,14 +153,6 @@ public class ExpandedAnimationController
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class ExpandedAnimationController
|
||||
}
|
||||
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 @@ public class ExpandedAnimationController
|
||||
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 @@ public class ExpandedAnimationController
|
||||
* @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 @@ public class ExpandedAnimationController
|
||||
* 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 @@ public class ExpandedAnimationController
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user