Merge "Ensure the bubble expanded view aligns with the pointer" into sc-v2-dev am: cc312e1054
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15144071 Change-Id: I69abce0f9bcd5e7ffecdc2943b82834dbe3e1c93
This commit is contained in:
@@ -25,6 +25,7 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW;
|
||||
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
|
||||
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.wm.shell.bubbles.BubblePositioner.MAX_HEIGHT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -60,7 +61,6 @@ import android.widget.LinearLayout;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.policy.ScreenDecorationsUtils;
|
||||
import com.android.launcher3.icons.IconNormalizer;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.TaskView;
|
||||
import com.android.wm.shell.common.AlphaOptimizedButton;
|
||||
@@ -77,7 +77,6 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
|
||||
// The triangle pointing to the expanded view
|
||||
private View mPointerView;
|
||||
private int mPointerMargin;
|
||||
@Nullable private int[] mExpandedViewContainerLocation;
|
||||
|
||||
private AlphaOptimizedButton mManageButton;
|
||||
@@ -102,9 +101,6 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
*/
|
||||
private boolean mIsAlphaAnimating = false;
|
||||
|
||||
private int mMinHeight;
|
||||
private int mOverflowHeight;
|
||||
private int mManageButtonHeight;
|
||||
private int mPointerWidth;
|
||||
private int mPointerHeight;
|
||||
private float mPointerRadius;
|
||||
@@ -348,12 +344,8 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
|
||||
void updateDimensions() {
|
||||
Resources res = getResources();
|
||||
mMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
|
||||
mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
|
||||
|
||||
updateFontSize();
|
||||
|
||||
mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
|
||||
mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
|
||||
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
|
||||
mPointerRadius = getResources().getDimensionPixelSize(R.dimen.bubble_pointer_radius);
|
||||
@@ -369,7 +361,6 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
updatePointerView();
|
||||
}
|
||||
|
||||
mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_height);
|
||||
if (mManageButton != null) {
|
||||
int visibility = mManageButton.getVisibility();
|
||||
removeView(mManageButton);
|
||||
@@ -633,12 +624,11 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
}
|
||||
|
||||
if ((mBubble != null && mTaskView != null) || mIsOverflow) {
|
||||
float desiredHeight = mIsOverflow
|
||||
? mPositioner.isLargeScreen() ? getMaxExpandedHeight() : mOverflowHeight
|
||||
: mBubble.getDesiredHeight(mContext);
|
||||
desiredHeight = Math.max(desiredHeight, mMinHeight);
|
||||
float height = Math.min(desiredHeight, getMaxExpandedHeight());
|
||||
height = Math.max(height, mMinHeight);
|
||||
float desiredHeight = mPositioner.getExpandedViewHeight(mBubble);
|
||||
int maxHeight = mPositioner.getMaxExpandedViewHeight(mIsOverflow);
|
||||
float height = desiredHeight == MAX_HEIGHT
|
||||
? maxHeight
|
||||
: Math.min(desiredHeight, maxHeight);
|
||||
FrameLayout.LayoutParams lp = mIsOverflow
|
||||
? (FrameLayout.LayoutParams) mOverflowView.getLayoutParams()
|
||||
: (FrameLayout.LayoutParams) mTaskView.getLayoutParams();
|
||||
@@ -662,23 +652,6 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxExpandedHeight() {
|
||||
int expandedContainerY = mExpandedViewContainerLocation != null
|
||||
// Remove top insets back here because availableRect.height would account for that
|
||||
? mExpandedViewContainerLocation[1] - mPositioner.getInsets().top
|
||||
: 0;
|
||||
int settingsHeight = mIsOverflow ? 0 : mManageButtonHeight;
|
||||
int pointerHeight = mPositioner.showBubblesVertically()
|
||||
? mPointerWidth
|
||||
: (int) (mPointerHeight - mPointerOverlap + mPointerMargin);
|
||||
return mPositioner.getAvailableRect().height()
|
||||
- expandedContainerY
|
||||
- getPaddingTop()
|
||||
- getPaddingBottom()
|
||||
- settingsHeight
|
||||
- pointerHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update appearance of the expanded view being displayed.
|
||||
*
|
||||
@@ -728,14 +701,11 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
: mPointerHeight - mPointerOverlap;
|
||||
setPadding((int) paddingLeft, (int) paddingTop, (int) paddingRight, 0);
|
||||
|
||||
final float expandedViewY = mPositioner.getExpandedViewY();
|
||||
// TODO: I don't understand why it works but it does - why normalized in portrait
|
||||
// & not in landscape? Am I missing ~2dp in the portrait expandedViewY calculation?
|
||||
final float normalizedSize = IconNormalizer.getNormalizedCircleSize(
|
||||
mPositioner.getBubbleSize());
|
||||
final float bubbleCenter = showVertically
|
||||
? bubblePosition + (mPositioner.getBubbleSize() / 2f) - expandedViewY
|
||||
: bubblePosition + (normalizedSize / 2f) - mPointerWidth;
|
||||
// Subtract the expandedViewY here because the pointer is placed within the expandedView.
|
||||
float pointerPosition = mPositioner.getPointerPosition(bubblePosition);
|
||||
final float bubbleCenter = mPositioner.showBubblesVertically()
|
||||
? pointerPosition - mPositioner.getExpandedViewY(mBubble, bubblePosition)
|
||||
: pointerPosition;
|
||||
// Post because we need the width of the view
|
||||
post(() -> {
|
||||
float pointerY;
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.view.WindowMetrics;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.icons.IconNormalizer;
|
||||
import com.android.wm.shell.R;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -58,6 +59,8 @@ public class BubblePositioner {
|
||||
|
||||
/** When the bubbles are collapsed in a stack only some of them are shown, this is how many. **/
|
||||
public static final int NUM_VISIBLE_WHEN_RESTING = 2;
|
||||
/** Indicates a bubble's height should be the maximum available space. **/
|
||||
public static final int MAX_HEIGHT = -1;
|
||||
|
||||
private Context mContext;
|
||||
private WindowManager mWindowManager;
|
||||
@@ -68,13 +71,16 @@ public class BubblePositioner {
|
||||
private int mMaxBubbles;
|
||||
|
||||
private int mBubbleSize;
|
||||
private int mBubbleBadgeSize;
|
||||
private int mSpacingBetweenBubbles;
|
||||
private int mExpandedViewLargeScreenWidth;
|
||||
private int mExpandedViewPadding;
|
||||
private int mPointerMargin;
|
||||
private float mPointerWidth;
|
||||
private float mPointerHeight;
|
||||
private int mPointerWidth;
|
||||
private int mPointerHeight;
|
||||
private int mPointerOverlap;
|
||||
private int mManageButtonHeight;
|
||||
private int mExpandedViewMinHeight;
|
||||
private int mOverflowHeight;
|
||||
|
||||
private PointF mPinLocation;
|
||||
private PointF mRestingStackPosition;
|
||||
@@ -151,7 +157,6 @@ public class BubblePositioner {
|
||||
|
||||
Resources res = mContext.getResources();
|
||||
mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size);
|
||||
mBubbleBadgeSize = res.getDimensionPixelSize(R.dimen.bubble_badge_size);
|
||||
mSpacingBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing);
|
||||
mDefaultMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);
|
||||
|
||||
@@ -161,6 +166,10 @@ public class BubblePositioner {
|
||||
mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
|
||||
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
|
||||
mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
|
||||
mPointerOverlap = res.getDimensionPixelSize(R.dimen.bubble_pointer_overlap);
|
||||
mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_height);
|
||||
mExpandedViewMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
|
||||
mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
|
||||
|
||||
mMaxBubbles = calculateMaxBubbles();
|
||||
|
||||
@@ -296,8 +305,8 @@ public class BubblePositioner {
|
||||
return mPaddings;
|
||||
}
|
||||
|
||||
/** Calculates the y position of the expanded view when it is expanded. */
|
||||
public float getExpandedViewY() {
|
||||
/** Gets the y position of the expanded view if it was top-aligned. */
|
||||
private float getExpandedViewYTopAligned() {
|
||||
final int top = getAvailableRect().top;
|
||||
if (showBubblesVertically()) {
|
||||
return top - mPointerWidth;
|
||||
@@ -306,6 +315,116 @@ public class BubblePositioner {
|
||||
}
|
||||
}
|
||||
|
||||
/** The maximum height the expanded view can be. */
|
||||
public int getMaxExpandedViewHeight(boolean isOverflow) {
|
||||
int paddingTop = showBubblesVertically()
|
||||
? 0
|
||||
: mPointerHeight;
|
||||
int settingsHeight = isOverflow ? 0 : mManageButtonHeight;
|
||||
// Subtract pointer size because it's laid out in LinearLayout with the expanded view.
|
||||
int pointerSize = showBubblesVertically()
|
||||
? mPointerWidth
|
||||
: (mPointerHeight + mPointerMargin);
|
||||
// Subtract top insets because availableRect.height would account for that
|
||||
int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top;
|
||||
return getAvailableRect().height()
|
||||
- expandedContainerY
|
||||
- paddingTop
|
||||
- settingsHeight
|
||||
- pointerSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the height for the bubble, ensuring a minimum height. If the height should be as
|
||||
* big as available, returns {@link #MAX_HEIGHT}.
|
||||
*/
|
||||
public float getExpandedViewHeight(BubbleViewProvider bubble) {
|
||||
boolean isOverflow = bubble == null || BubbleOverflow.KEY.equals(bubble.getKey());
|
||||
float desiredHeight = isOverflow
|
||||
? mOverflowHeight
|
||||
: ((Bubble) bubble).getDesiredHeight(mContext);
|
||||
int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight;
|
||||
desiredHeight = Math.max(manageButtonHeight + desiredHeight, mExpandedViewMinHeight);
|
||||
if (desiredHeight > getMaxExpandedViewHeight(isOverflow)) {
|
||||
return MAX_HEIGHT;
|
||||
}
|
||||
return desiredHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y position for the expanded view. This is the position on screen of the top
|
||||
* horizontal line of the expanded view.
|
||||
*
|
||||
* @param bubble the bubble being positioned.
|
||||
* @param bubblePosition the x position of the bubble if showing on top, the y position of the
|
||||
* bubble if showing vertically.
|
||||
* @return the y position for the expanded view.
|
||||
*/
|
||||
public float getExpandedViewY(BubbleViewProvider bubble, float bubblePosition) {
|
||||
boolean isOverflow = bubble == null || BubbleOverflow.KEY.equals(bubble.getKey());
|
||||
float expandedViewHeight = getExpandedViewHeight(bubble);
|
||||
float topAlignment = getExpandedViewYTopAligned();
|
||||
if (!showBubblesVertically() || expandedViewHeight == MAX_HEIGHT) {
|
||||
// Top-align when bubbles are shown at the top or are max size.
|
||||
return topAlignment;
|
||||
}
|
||||
// If we're here, we're showing vertically & developer has made height less than maximum.
|
||||
int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight;
|
||||
float pointerPosition = getPointerPosition(bubblePosition);
|
||||
float bottomIfCentered = pointerPosition + (expandedViewHeight / 2) + manageButtonHeight;
|
||||
float topIfCentered = pointerPosition - (expandedViewHeight / 2);
|
||||
if (topIfCentered > mPositionRect.top && mPositionRect.bottom > bottomIfCentered) {
|
||||
// Center it
|
||||
return pointerPosition - mPointerWidth - (expandedViewHeight / 2f);
|
||||
} else if (topIfCentered <= mPositionRect.top) {
|
||||
// Top align
|
||||
return topAlignment;
|
||||
} else {
|
||||
// Bottom align
|
||||
return mPositionRect.bottom - manageButtonHeight - expandedViewHeight - mPointerWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The position the pointer points to, the center of the bubble.
|
||||
*
|
||||
* @param bubblePosition the x position of the bubble if showing on top, the y position of the
|
||||
* bubble if showing vertically.
|
||||
* @return the position the tip of the pointer points to. The x position if showing on top, the
|
||||
* y position if showing vertically.
|
||||
*/
|
||||
public float getPointerPosition(float bubblePosition) {
|
||||
// TODO: I don't understand why it works but it does - why normalized in portrait
|
||||
// & not in landscape? Am I missing ~2dp in the portrait expandedViewY calculation?
|
||||
final float normalizedSize = IconNormalizer.getNormalizedCircleSize(
|
||||
getBubbleSize());
|
||||
return showBubblesVertically()
|
||||
? bubblePosition + (getBubbleSize() / 2f)
|
||||
: bubblePosition + (normalizedSize / 2f) - mPointerWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
|
||||
* row. When in landscape or on a large screen, they show at the left or right side in a
|
||||
* vertical row. This method accounts for screen orientation and will return an x or y value
|
||||
* for the position of the bubble in the row.
|
||||
*
|
||||
* @param index bubble index in the row.
|
||||
* @param numberOfBubbles the number of bubbles (including the overflow) in the row.
|
||||
* @return the y position of the bubble if showing vertically and the x position if showing
|
||||
* horizontally.
|
||||
*/
|
||||
public float getBubbleXOrYForOrientation(int index, int numberOfBubbles) {
|
||||
final float positionInBar = index * (mBubbleSize + mSpacingBetweenBubbles);
|
||||
final float expandedStackSize = (numberOfBubbles * mBubbleSize)
|
||||
+ ((numberOfBubbles - 1) * mSpacingBetweenBubbles);
|
||||
final float centerPosition = showBubblesVertically()
|
||||
? mPositionRect.centerY()
|
||||
: mPositionRect.centerX();
|
||||
final float rowStart = centerPosition - (expandedStackSize / 2f);
|
||||
return rowStart + positionInBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stack's most recent position along the edge of the screen. This is saved when the
|
||||
* last bubble is removed, so that the stack can be restored in its previous position.
|
||||
|
||||
@@ -874,8 +874,10 @@ public class BubbleStackView extends FrameLayout
|
||||
mExpandedAnimationController.expandFromStack(() -> {
|
||||
afterExpandedViewAnimation();
|
||||
} /* after */);
|
||||
final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
|
||||
getBubbleIndex(mExpandedBubble));
|
||||
mExpandedViewContainer.setTranslationX(0f);
|
||||
mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
|
||||
mExpandedViewContainer.setTranslationY(translationY);
|
||||
mExpandedViewContainer.setAlpha(1f);
|
||||
}
|
||||
removeOnLayoutChangeListener(mOrientationChangedListener);
|
||||
@@ -1524,6 +1526,7 @@ public class BubbleStackView extends FrameLayout
|
||||
bubble.cleanupViews();
|
||||
}
|
||||
updatePointerPosition();
|
||||
updateExpandedView();
|
||||
logBubbleEvent(bubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
|
||||
return;
|
||||
}
|
||||
@@ -1815,9 +1818,10 @@ public class BubbleStackView extends FrameLayout
|
||||
mTaskbarScrim.setVisibility(VISIBLE);
|
||||
mTaskbarScrim.animate().alpha(1f).start();
|
||||
}
|
||||
|
||||
final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
|
||||
getBubbleIndex(mExpandedBubble));
|
||||
mExpandedViewContainer.setTranslationX(0f);
|
||||
mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
|
||||
mExpandedViewContainer.setTranslationY(translationY);
|
||||
mExpandedViewContainer.setAlpha(1f);
|
||||
|
||||
int index;
|
||||
@@ -1866,7 +1870,7 @@ public class BubbleStackView extends FrameLayout
|
||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||
bubbleWillBeAt + mBubbleSize / 2f,
|
||||
mPositioner.getExpandedViewY());
|
||||
translationY);
|
||||
}
|
||||
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
|
||||
|
||||
@@ -1970,7 +1974,7 @@ public class BubbleStackView extends FrameLayout
|
||||
mExpandedViewContainerMatrix.setScale(
|
||||
1f, 1f,
|
||||
expandingFromBubbleAt + mBubbleSize / 2f,
|
||||
mPositioner.getExpandedViewY());
|
||||
mPositioner.getExpandedViewY(mExpandedBubble, index));
|
||||
}
|
||||
|
||||
mExpandedViewAlphaAnimator.reverse();
|
||||
@@ -2077,7 +2081,7 @@ public class BubbleStackView extends FrameLayout
|
||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||
expandingFromBubbleDestination + mBubbleSize / 2f,
|
||||
mPositioner.getExpandedViewY());
|
||||
mPositioner.getExpandedViewY(mExpandedBubble, expandingFromBubbleDestination));
|
||||
}
|
||||
|
||||
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
|
||||
@@ -2698,7 +2702,9 @@ public class BubbleStackView extends FrameLayout
|
||||
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
|
||||
}
|
||||
if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
|
||||
mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
|
||||
mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY(mExpandedBubble,
|
||||
mExpandedAnimationController.getBubbleXOrYForOrientation(
|
||||
getBubbleIndex(mExpandedBubble))));
|
||||
mExpandedViewContainer.setTranslationX(0f);
|
||||
mExpandedBubble.getExpandedView().updateView(
|
||||
mExpandedViewContainer.getLocationOnScreen());
|
||||
|
||||
@@ -83,12 +83,6 @@ public class ExpandedAnimationController
|
||||
private float mBubblePaddingTop;
|
||||
/** Size of each bubble. */
|
||||
private float mBubbleSizePx;
|
||||
/** Max number of bubbles shown in row above expanded view. */
|
||||
private int mBubblesMaxRendered;
|
||||
/** Max amount of space to have between bubbles when expanded. */
|
||||
private int mBubblesMaxSpace;
|
||||
/** Amount of space between the bubbles when expanded. */
|
||||
private float mSpaceBetweenBubbles;
|
||||
/** Whether the expand / collapse animation is running. */
|
||||
private boolean mAnimatingExpand = false;
|
||||
|
||||
@@ -211,8 +205,6 @@ public class ExpandedAnimationController
|
||||
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
|
||||
mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
|
||||
mBubbleSizePx = mPositioner.getBubbleSize();
|
||||
mBubblesMaxRendered = mPositioner.getMaxBubbles();
|
||||
mSpaceBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -628,14 +620,13 @@ public class ExpandedAnimationController
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - could move to method on bubblePositioner if mSpaceBetweenBubbles gets moved
|
||||
/**
|
||||
* When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
|
||||
* row. When in landscape or on a large screen, they show at the left or right side in a
|
||||
* vertical row. This method accounts for screen orientation and will return an x or y value
|
||||
* for the position of the bubble in the row.
|
||||
*
|
||||
* @param index Bubble index in row.
|
||||
* @param index bubble index in the row.
|
||||
* @return the y position of the bubble if showing vertically and the x position if showing
|
||||
* horizontally.
|
||||
*/
|
||||
@@ -643,15 +634,6 @@ public class ExpandedAnimationController
|
||||
if (mLayout == null) {
|
||||
return 0;
|
||||
}
|
||||
final float positionInBar = index * (mBubbleSizePx + mSpaceBetweenBubbles);
|
||||
Rect availableRect = mPositioner.getAvailableRect();
|
||||
final boolean isLandscape = mPositioner.showBubblesVertically();
|
||||
final float expandedStackSize = (mLayout.getChildCount() * mBubbleSizePx)
|
||||
+ ((mLayout.getChildCount() - 1) * mSpaceBetweenBubbles);
|
||||
final float centerPosition = isLandscape
|
||||
? availableRect.centerY()
|
||||
: availableRect.centerX();
|
||||
final float rowStart = centerPosition - (expandedStackSize / 2f);
|
||||
return rowStart + positionInBar;
|
||||
return mPositioner.getBubbleXOrYForOrientation(index, mLayout.getChildCount());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user