Merge "Center bubbles horizontally on large screens" into sc-v2-dev
This commit is contained in:
@@ -696,8 +696,10 @@ public class BubbleExpandedView extends LinearLayout {
|
|||||||
? mPointerHeight - mPointerOverlap
|
? mPointerHeight - mPointerOverlap
|
||||||
: 0;
|
: 0;
|
||||||
final float paddingRight = (showVertically && !onLeft)
|
final float paddingRight = (showVertically && !onLeft)
|
||||||
? mPointerHeight - mPointerOverlap : 0;
|
? mPointerHeight - mPointerOverlap
|
||||||
final float paddingTop = showVertically ? 0
|
: 0;
|
||||||
|
final float paddingTop = showVertically
|
||||||
|
? 0
|
||||||
: mPointerHeight - mPointerOverlap;
|
: mPointerHeight - mPointerOverlap;
|
||||||
setPadding((int) paddingLeft, (int) paddingTop, (int) paddingRight, 0);
|
setPadding((int) paddingLeft, (int) paddingTop, (int) paddingRight, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -79,14 +79,18 @@ public class BubblePositioner {
|
|||||||
|
|
||||||
private int mBubbleSize;
|
private int mBubbleSize;
|
||||||
private int mSpacingBetweenBubbles;
|
private int mSpacingBetweenBubbles;
|
||||||
private float mExpandedViewLargeScreenWidth;
|
|
||||||
|
private int mExpandedViewMinHeight;
|
||||||
|
private int mExpandedViewLargeScreenWidth;
|
||||||
|
private int mExpandedViewLargeScreenInset;
|
||||||
|
|
||||||
private int mOverflowWidth;
|
private int mOverflowWidth;
|
||||||
private int mExpandedViewPadding;
|
private int mExpandedViewPadding;
|
||||||
private int mPointerMargin;
|
private int mPointerMargin;
|
||||||
private int mPointerWidth;
|
private int mPointerWidth;
|
||||||
private int mPointerHeight;
|
private int mPointerHeight;
|
||||||
|
private int mPointerOverlap;
|
||||||
private int mManageButtonHeight;
|
private int mManageButtonHeight;
|
||||||
private int mExpandedViewMinHeight;
|
|
||||||
private int mOverflowHeight;
|
private int mOverflowHeight;
|
||||||
private int mMinimumFlyoutWidthLargeScreen;
|
private int mMinimumFlyoutWidthLargeScreen;
|
||||||
|
|
||||||
@@ -168,15 +172,20 @@ public class BubblePositioner {
|
|||||||
mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size);
|
mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size);
|
||||||
mSpacingBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing);
|
mSpacingBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing);
|
||||||
mDefaultMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);
|
mDefaultMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);
|
||||||
mExpandedViewLargeScreenWidth = bounds.width() * EXPANDED_VIEW_LARGE_SCREEN_WIDTH_PERCENT;
|
mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
|
||||||
|
mExpandedViewLargeScreenWidth = (int) (bounds.width()
|
||||||
|
* EXPANDED_VIEW_LARGE_SCREEN_WIDTH_PERCENT);
|
||||||
|
mExpandedViewLargeScreenInset = mIsLargeScreen
|
||||||
|
? (bounds.width() - mExpandedViewLargeScreenWidth) / 2
|
||||||
|
: mExpandedViewPadding;
|
||||||
mOverflowWidth = mIsLargeScreen
|
mOverflowWidth = mIsLargeScreen
|
||||||
? (int) mExpandedViewLargeScreenWidth
|
? mExpandedViewLargeScreenWidth
|
||||||
: res.getDimensionPixelSize(
|
: res.getDimensionPixelSize(
|
||||||
R.dimen.bubble_expanded_view_phone_landscape_overflow_width);
|
R.dimen.bubble_expanded_view_phone_landscape_overflow_width);
|
||||||
mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
|
|
||||||
mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
|
mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
|
||||||
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
|
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
|
||||||
mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
|
mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
|
||||||
|
mPointerOverlap = res.getDimensionPixelSize(R.dimen.bubble_pointer_overlap);
|
||||||
mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_total_height);
|
mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_total_height);
|
||||||
mExpandedViewMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
|
mExpandedViewMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
|
||||||
mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
|
mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
|
||||||
@@ -294,27 +303,46 @@ public class BubblePositioner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the left & right padding for the bubble expanded view.
|
* Calculates the padding for the bubble expanded view.
|
||||||
*
|
*
|
||||||
* On larger screens the width of the expanded view is restricted via this padding.
|
* Some specifics:
|
||||||
* On landscape the bubble overflow expanded view is also restricted via this padding.
|
* On large screens the width of the expanded view is restricted via this padding.
|
||||||
|
* On phone landscape the bubble overflow expanded view is also restricted via this padding.
|
||||||
|
* On large screens & landscape no top padding is set, the top position is set via translation.
|
||||||
|
* On phone portrait top padding is set as the space between the tip of the pointer and the
|
||||||
|
* bubble.
|
||||||
|
* When the overflow is shown it doesn't have the manage button to pad out the bottom so
|
||||||
|
* padding is added.
|
||||||
*/
|
*/
|
||||||
public int[] getExpandedViewPadding(boolean onLeft, boolean isOverflow) {
|
public int[] getExpandedViewContainerPadding(boolean onLeft, boolean isOverflow) {
|
||||||
|
final int pointerTotalHeight = mPointerHeight - mPointerOverlap;
|
||||||
|
if (mIsLargeScreen) {
|
||||||
|
// [left, top, right, bottom]
|
||||||
|
mPaddings[0] = onLeft
|
||||||
|
? mExpandedViewLargeScreenInset - pointerTotalHeight
|
||||||
|
: mExpandedViewLargeScreenInset;
|
||||||
|
mPaddings[1] = 0;
|
||||||
|
mPaddings[2] = onLeft
|
||||||
|
? mExpandedViewLargeScreenInset
|
||||||
|
: mExpandedViewLargeScreenInset - pointerTotalHeight;
|
||||||
|
// Overflow doesn't show manage button / get padding from it so add padding here for it
|
||||||
|
mPaddings[3] = isOverflow ? mExpandedViewPadding : 0;
|
||||||
|
return mPaddings;
|
||||||
|
} else {
|
||||||
int leftPadding = mInsets.left + mExpandedViewPadding;
|
int leftPadding = mInsets.left + mExpandedViewPadding;
|
||||||
int rightPadding = mInsets.right + mExpandedViewPadding;
|
int rightPadding = mInsets.right + mExpandedViewPadding;
|
||||||
final boolean isLargeOrOverflow = mIsLargeScreen || isOverflow;
|
|
||||||
final float expandedViewWidth = isOverflow
|
final float expandedViewWidth = isOverflow
|
||||||
? mOverflowWidth
|
? mOverflowWidth
|
||||||
: mExpandedViewLargeScreenWidth;
|
: mExpandedViewLargeScreenWidth;
|
||||||
if (showBubblesVertically()) {
|
if (showBubblesVertically()) {
|
||||||
if (!onLeft) {
|
if (!onLeft) {
|
||||||
rightPadding += mBubbleSize - mPointerHeight;
|
rightPadding += mBubbleSize - pointerTotalHeight;
|
||||||
leftPadding += isLargeOrOverflow
|
leftPadding += isOverflow
|
||||||
? (mPositionRect.width() - rightPadding - expandedViewWidth)
|
? (mPositionRect.width() - rightPadding - expandedViewWidth)
|
||||||
: 0;
|
: 0;
|
||||||
} else {
|
} else {
|
||||||
leftPadding += mBubbleSize - mPointerHeight;
|
leftPadding += mBubbleSize - pointerTotalHeight;
|
||||||
rightPadding += isLargeOrOverflow
|
rightPadding += isOverflow
|
||||||
? (mPositionRect.width() - leftPadding - expandedViewWidth)
|
? (mPositionRect.width() - leftPadding - expandedViewWidth)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
@@ -326,34 +354,42 @@ public class BubblePositioner {
|
|||||||
mPaddings[3] = 0;
|
mPaddings[3] = 0;
|
||||||
return mPaddings;
|
return mPaddings;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets the y position of the expanded view if it was top-aligned. */
|
/** Gets the y position of the expanded view if it was top-aligned. */
|
||||||
private float getExpandedViewYTopAligned() {
|
private float getExpandedViewYTopAligned() {
|
||||||
final int top = getAvailableRect().top;
|
final int top = getAvailableRect().top;
|
||||||
if (showBubblesVertically()) {
|
if (showBubblesVertically()) {
|
||||||
return top - mPointerWidth;
|
return top - mPointerWidth + mExpandedViewPadding;
|
||||||
} else {
|
} else {
|
||||||
return top + mBubbleSize + mPointerMargin;
|
return top + mBubbleSize + mPointerMargin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The maximum height the expanded view can be. */
|
public float getExpandedBubblesY() {
|
||||||
|
return getAvailableRect().top + mExpandedViewPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the maximum height the expanded view can be depending on where it's placed on
|
||||||
|
* the screen and the size of the elements around it (e.g. padding, pointer, manage button).
|
||||||
|
*/
|
||||||
public int getMaxExpandedViewHeight(boolean isOverflow) {
|
public int getMaxExpandedViewHeight(boolean isOverflow) {
|
||||||
|
// Subtract top insets because availableRect.height would account for that
|
||||||
|
int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top;
|
||||||
int paddingTop = showBubblesVertically()
|
int paddingTop = showBubblesVertically()
|
||||||
? 0
|
? 0
|
||||||
: mPointerHeight;
|
: mPointerHeight;
|
||||||
int settingsHeight = isOverflow ? 0 : mManageButtonHeight;
|
|
||||||
// Subtract pointer size because it's laid out in LinearLayout with the expanded view.
|
// Subtract pointer size because it's laid out in LinearLayout with the expanded view.
|
||||||
int pointerSize = showBubblesVertically()
|
int pointerSize = showBubblesVertically()
|
||||||
? mPointerWidth
|
? mPointerWidth
|
||||||
: (mPointerHeight + mPointerMargin);
|
: (mPointerHeight + mPointerMargin);
|
||||||
// Subtract top insets because availableRect.height would account for that
|
int bottomPadding = isOverflow ? mExpandedViewPadding : mManageButtonHeight;
|
||||||
int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top;
|
|
||||||
return getAvailableRect().height()
|
return getAvailableRect().height()
|
||||||
- expandedContainerY
|
- expandedContainerY
|
||||||
- paddingTop
|
- paddingTop
|
||||||
- settingsHeight
|
- pointerSize
|
||||||
- pointerSize;
|
- bottomPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,11 +398,14 @@ public class BubblePositioner {
|
|||||||
*/
|
*/
|
||||||
public float getExpandedViewHeight(BubbleViewProvider bubble) {
|
public float getExpandedViewHeight(BubbleViewProvider bubble) {
|
||||||
boolean isOverflow = bubble == null || BubbleOverflow.KEY.equals(bubble.getKey());
|
boolean isOverflow = bubble == null || BubbleOverflow.KEY.equals(bubble.getKey());
|
||||||
|
if (isOverflow && showBubblesVertically() && !mIsLargeScreen) {
|
||||||
|
// overflow in landscape on phone is max
|
||||||
|
return MAX_HEIGHT;
|
||||||
|
}
|
||||||
float desiredHeight = isOverflow
|
float desiredHeight = isOverflow
|
||||||
? mOverflowHeight
|
? mOverflowHeight
|
||||||
: ((Bubble) bubble).getDesiredHeight(mContext);
|
: ((Bubble) bubble).getDesiredHeight(mContext);
|
||||||
int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight;
|
desiredHeight = Math.max(desiredHeight, mExpandedViewMinHeight);
|
||||||
desiredHeight = Math.max(manageButtonHeight + desiredHeight, mExpandedViewMinHeight);
|
|
||||||
if (desiredHeight > getMaxExpandedViewHeight(isOverflow)) {
|
if (desiredHeight > getMaxExpandedViewHeight(isOverflow)) {
|
||||||
return MAX_HEIGHT;
|
return MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
@@ -391,7 +430,7 @@ public class BubblePositioner {
|
|||||||
return topAlignment;
|
return topAlignment;
|
||||||
}
|
}
|
||||||
// If we're here, we're showing vertically & developer has made height less than maximum.
|
// If we're here, we're showing vertically & developer has made height less than maximum.
|
||||||
int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight;
|
int manageButtonHeight = isOverflow ? mExpandedViewPadding : mManageButtonHeight;
|
||||||
float pointerPosition = getPointerPosition(bubblePosition);
|
float pointerPosition = getPointerPosition(bubblePosition);
|
||||||
float bottomIfCentered = pointerPosition + (expandedViewHeight / 2) + manageButtonHeight;
|
float bottomIfCentered = pointerPosition + (expandedViewHeight / 2) + manageButtonHeight;
|
||||||
float topIfCentered = pointerPosition - (expandedViewHeight / 2);
|
float topIfCentered = pointerPosition - (expandedViewHeight / 2);
|
||||||
@@ -426,25 +465,40 @@ public class BubblePositioner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
|
* Returns the position of the bubble on-screen when the stack is expanded.
|
||||||
* 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 index the index of the bubble in the stack.
|
||||||
* @param numberOfBubbles the number of bubbles (including the overflow) in the row.
|
* @param numberOfBubbles the total number of bubbles in the stack.
|
||||||
* @return the y position of the bubble if showing vertically and the x position if showing
|
* @param onLeftEdge whether the stack would rest on the left edge of the screen when collapsed.
|
||||||
* horizontally.
|
* @return the x, y position of the bubble on-screen when the stack is expanded.
|
||||||
*/
|
*/
|
||||||
public float getBubbleXOrYForOrientation(int index, int numberOfBubbles) {
|
public PointF getExpandedBubbleXY(int index, int numberOfBubbles, boolean onLeftEdge) {
|
||||||
final float positionInBar = index * (mBubbleSize + mSpacingBetweenBubbles);
|
final float positionInRow = index * (mBubbleSize + mSpacingBetweenBubbles);
|
||||||
final float expandedStackSize = (numberOfBubbles * mBubbleSize)
|
final float expandedStackSize = (numberOfBubbles * mBubbleSize)
|
||||||
+ ((numberOfBubbles - 1) * mSpacingBetweenBubbles);
|
+ ((numberOfBubbles - 1) * mSpacingBetweenBubbles);
|
||||||
final float centerPosition = showBubblesVertically()
|
final float centerPosition = showBubblesVertically()
|
||||||
? mPositionRect.centerY()
|
? mPositionRect.centerY()
|
||||||
: mPositionRect.centerX();
|
: mPositionRect.centerX();
|
||||||
|
// alignment - centered on the edge
|
||||||
final float rowStart = centerPosition - (expandedStackSize / 2f);
|
final float rowStart = centerPosition - (expandedStackSize / 2f);
|
||||||
return rowStart + positionInBar;
|
float x;
|
||||||
|
float y;
|
||||||
|
if (showBubblesVertically()) {
|
||||||
|
y = rowStart + positionInRow;
|
||||||
|
int left = mIsLargeScreen
|
||||||
|
? mExpandedViewLargeScreenInset - mExpandedViewPadding - mBubbleSize
|
||||||
|
: mPositionRect.left;
|
||||||
|
int right = mIsLargeScreen
|
||||||
|
? mPositionRect.right - mExpandedViewLargeScreenInset + mExpandedViewPadding
|
||||||
|
: mPositionRect.right - mBubbleSize;
|
||||||
|
x = onLeftEdge
|
||||||
|
? left
|
||||||
|
: right;
|
||||||
|
} else {
|
||||||
|
y = mPositionRect.top + mExpandedViewPadding;
|
||||||
|
x = rowStart + positionInRow;
|
||||||
|
}
|
||||||
|
return new PointF(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -458,6 +512,17 @@ public class BubblePositioner {
|
|||||||
return mScreenRect.width() * FLYOUT_MAX_WIDTH_PERCENT;
|
return mScreenRect.width() * FLYOUT_MAX_WIDTH_PERCENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether the stack is considered on the left side of the screen.
|
||||||
|
*/
|
||||||
|
public boolean isStackOnLeft(PointF currentStackPosition) {
|
||||||
|
if (currentStackPosition == null) {
|
||||||
|
currentStackPosition = getRestingPosition();
|
||||||
|
}
|
||||||
|
final int stackCenter = (int) currentStackPosition.x + mBubbleSize / 2;
|
||||||
|
return stackCenter < mScreenRect.width() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the stack's most recent position along the edge of the screen. This is saved when the
|
* 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.
|
* last bubble is removed, so that the stack can be restored in its previous position.
|
||||||
|
|||||||
@@ -778,8 +778,8 @@ public class BubbleStackView extends FrameLayout
|
|||||||
floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut,
|
floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut,
|
||||||
this::animateShadows /* onStackAnimationFinished */, mPositioner);
|
this::animateShadows /* onStackAnimationFinished */, mPositioner);
|
||||||
|
|
||||||
mExpandedAnimationController = new ExpandedAnimationController(
|
mExpandedAnimationController = new ExpandedAnimationController(mPositioner,
|
||||||
mPositioner, mExpandedViewPadding, onBubbleAnimatedOut);
|
onBubbleAnimatedOut);
|
||||||
mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
|
mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
|
||||||
|
|
||||||
// Force LTR by default since most of the Bubbles UI is positioned manually by the user, or
|
// Force LTR by default since most of the Bubbles UI is positioned manually by the user, or
|
||||||
@@ -1869,28 +1869,28 @@ public class BubbleStackView extends FrameLayout
|
|||||||
maybeShowManageEdu();
|
maybeShowManageEdu();
|
||||||
}
|
}
|
||||||
} /* after */);
|
} /* after */);
|
||||||
|
|
||||||
final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
|
|
||||||
getBubbleIndex(mExpandedBubble));
|
|
||||||
mExpandedViewContainer.setTranslationX(0f);
|
|
||||||
mExpandedViewContainer.setTranslationY(translationY);
|
|
||||||
mExpandedViewContainer.setAlpha(1f);
|
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) {
|
if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) {
|
||||||
index = mBubbleData.getBubbles().size();
|
index = mBubbleData.getBubbles().size();
|
||||||
} else {
|
} else {
|
||||||
index = getBubbleIndex(mExpandedBubble);
|
index = getBubbleIndex(mExpandedBubble);
|
||||||
}
|
}
|
||||||
// Position of the bubble we're expanding, once it's settled in its row.
|
PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleContainer.getChildCount(),
|
||||||
final float bubbleWillBeAt =
|
mStackOnLeftOrWillBe);
|
||||||
mExpandedAnimationController.getBubbleXOrYForOrientation(index);
|
final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
|
||||||
|
mPositioner.showBubblesVertically() ? p.y : p.x);
|
||||||
|
mExpandedViewContainer.setTranslationX(0f);
|
||||||
|
mExpandedViewContainer.setTranslationY(translationY);
|
||||||
|
mExpandedViewContainer.setAlpha(1f);
|
||||||
|
|
||||||
// How far horizontally the bubble will be animating. We'll wait a bit longer for bubbles
|
// How far horizontally the bubble will be animating. We'll wait a bit longer for bubbles
|
||||||
// that are animating farther, so that the expanded view doesn't move as much.
|
// that are animating farther, so that the expanded view doesn't move as much.
|
||||||
final float relevantStackPosition = showVertically
|
final float relevantStackPosition = showVertically
|
||||||
? mStackAnimationController.getStackPosition().y
|
? mStackAnimationController.getStackPosition().y
|
||||||
: mStackAnimationController.getStackPosition().x;
|
: mStackAnimationController.getStackPosition().x;
|
||||||
|
final float bubbleWillBeAt = showVertically
|
||||||
|
? p.y
|
||||||
|
: p.x;
|
||||||
final float distanceAnimated = Math.abs(bubbleWillBeAt - relevantStackPosition);
|
final float distanceAnimated = Math.abs(bubbleWillBeAt - relevantStackPosition);
|
||||||
|
|
||||||
// Wait for the path animation target to reach its end, and add a small amount of extra time
|
// Wait for the path animation target to reach its end, and add a small amount of extra time
|
||||||
@@ -1907,22 +1907,22 @@ public class BubbleStackView extends FrameLayout
|
|||||||
// Set the pivot point for the scale, so the expanded view animates out from the bubble.
|
// Set the pivot point for the scale, so the expanded view animates out from the bubble.
|
||||||
if (showVertically) {
|
if (showVertically) {
|
||||||
float pivotX;
|
float pivotX;
|
||||||
float pivotY = bubbleWillBeAt + mBubbleSize / 2f;
|
|
||||||
if (mStackOnLeftOrWillBe) {
|
if (mStackOnLeftOrWillBe) {
|
||||||
pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
|
pivotX = p.x + mBubbleSize + mExpandedViewPadding;
|
||||||
} else {
|
} else {
|
||||||
pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
|
pivotX = p.x - mExpandedViewPadding;
|
||||||
}
|
}
|
||||||
mExpandedViewContainerMatrix.setScale(
|
mExpandedViewContainerMatrix.setScale(
|
||||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||||
pivotX, pivotY);
|
pivotX,
|
||||||
|
p.y + mBubbleSize / 2f);
|
||||||
} else {
|
} else {
|
||||||
mExpandedViewContainerMatrix.setScale(
|
mExpandedViewContainerMatrix.setScale(
|
||||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||||
bubbleWillBeAt + mBubbleSize / 2f,
|
p.x + mBubbleSize / 2f,
|
||||||
translationY);
|
p.y + mBubbleSize + mExpandedViewPadding);
|
||||||
}
|
}
|
||||||
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
|
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
|
||||||
|
|
||||||
@@ -1959,6 +1959,7 @@ public class BubbleStackView extends FrameLayout
|
|||||||
mExpandedViewContainerMatrix);
|
mExpandedViewContainerMatrix);
|
||||||
})
|
})
|
||||||
.withEndActions(() -> {
|
.withEndActions(() -> {
|
||||||
|
mExpandedViewContainer.setAnimationMatrix(null);
|
||||||
afterExpandedViewAnimation();
|
afterExpandedViewAnimation();
|
||||||
if (mExpandedBubble != null
|
if (mExpandedBubble != null
|
||||||
&& mExpandedBubble.getExpandedView() != null) {
|
&& mExpandedBubble.getExpandedView() != null) {
|
||||||
@@ -2009,12 +2010,11 @@ public class BubbleStackView extends FrameLayout
|
|||||||
index = mBubbleData.getBubbles().indexOf(mExpandedBubble);
|
index = mBubbleData.getBubbles().indexOf(mExpandedBubble);
|
||||||
}
|
}
|
||||||
// Value the bubble is animating from (back into the stack).
|
// Value the bubble is animating from (back into the stack).
|
||||||
final float expandingFromBubbleAt =
|
final PointF p = mPositioner.getExpandedBubbleXY(index,
|
||||||
mExpandedAnimationController.getBubbleXOrYForOrientation(index);
|
mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe);
|
||||||
final boolean showVertically = mPositioner.showBubblesVertically();
|
|
||||||
if (mPositioner.showBubblesVertically()) {
|
if (mPositioner.showBubblesVertically()) {
|
||||||
float pivotX;
|
float pivotX;
|
||||||
float pivotY = expandingFromBubbleAt + mBubbleSize / 2f;
|
float pivotY = p.y + mBubbleSize / 2f;
|
||||||
if (mStackOnLeftOrWillBe) {
|
if (mStackOnLeftOrWillBe) {
|
||||||
pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
|
pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
|
||||||
} else {
|
} else {
|
||||||
@@ -2026,8 +2026,8 @@ public class BubbleStackView extends FrameLayout
|
|||||||
} else {
|
} else {
|
||||||
mExpandedViewContainerMatrix.setScale(
|
mExpandedViewContainerMatrix.setScale(
|
||||||
1f, 1f,
|
1f, 1f,
|
||||||
expandingFromBubbleAt + mBubbleSize / 2f,
|
p.x + mBubbleSize / 2f,
|
||||||
mPositioner.getExpandedViewY(mExpandedBubble, index));
|
p.y + mBubbleSize + mExpandedViewPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
mExpandedViewAlphaAnimator.reverse();
|
mExpandedViewAlphaAnimator.reverse();
|
||||||
@@ -2105,32 +2105,31 @@ public class BubbleStackView extends FrameLayout
|
|||||||
|
|
||||||
boolean isOverflow = mExpandedBubble != null
|
boolean isOverflow = mExpandedBubble != null
|
||||||
&& mExpandedBubble.getKey().equals(BubbleOverflow.KEY);
|
&& mExpandedBubble.getKey().equals(BubbleOverflow.KEY);
|
||||||
float expandingFromBubbleDestination =
|
PointF p = mPositioner.getExpandedBubbleXY(isOverflow
|
||||||
mExpandedAnimationController.getBubbleXOrYForOrientation(isOverflow
|
? mBubbleContainer.getChildCount() - 1
|
||||||
? getBubbleCount()
|
: mBubbleData.getBubbles().indexOf(mExpandedBubble),
|
||||||
: mBubbleData.getBubbles().indexOf(mExpandedBubble));
|
mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe);
|
||||||
|
|
||||||
mExpandedViewContainer.setAlpha(1f);
|
mExpandedViewContainer.setAlpha(1f);
|
||||||
mExpandedViewContainer.setVisibility(View.VISIBLE);
|
mExpandedViewContainer.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
if (mPositioner.showBubblesVertically()) {
|
if (mPositioner.showBubblesVertically()) {
|
||||||
float pivotX;
|
float pivotX;
|
||||||
float pivotY = expandingFromBubbleDestination + mBubbleSize / 2f;
|
float pivotY = p.y + mBubbleSize / 2f;
|
||||||
if (mStackOnLeftOrWillBe) {
|
if (mStackOnLeftOrWillBe) {
|
||||||
pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
|
pivotX = p.x + mBubbleSize + mExpandedViewPadding;
|
||||||
} else {
|
} else {
|
||||||
pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
|
pivotX = p.x - mExpandedViewPadding;
|
||||||
|
|
||||||
}
|
}
|
||||||
mExpandedViewContainerMatrix.setScale(
|
mExpandedViewContainerMatrix.setScale(
|
||||||
0f, 0f,
|
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||||
|
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||||
pivotX, pivotY);
|
pivotX, pivotY);
|
||||||
} else {
|
} else {
|
||||||
mExpandedViewContainerMatrix.setScale(
|
mExpandedViewContainerMatrix.setScale(
|
||||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||||
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
|
||||||
expandingFromBubbleDestination + mBubbleSize / 2f,
|
p.x + mBubbleSize / 2f,
|
||||||
mPositioner.getExpandedViewY(mExpandedBubble, expandingFromBubbleDestination));
|
p.y + mBubbleSize + mExpandedViewPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
|
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
|
||||||
@@ -2155,6 +2154,7 @@ public class BubbleStackView extends FrameLayout
|
|||||||
.withEndActions(() -> {
|
.withEndActions(() -> {
|
||||||
mExpandedViewTemporarilyHidden = false;
|
mExpandedViewTemporarilyHidden = false;
|
||||||
mIsBubbleSwitchAnimating = false;
|
mIsBubbleSwitchAnimating = false;
|
||||||
|
mExpandedViewContainer.setAnimationMatrix(null);
|
||||||
})
|
})
|
||||||
.start();
|
.start();
|
||||||
}, 25);
|
}, 25);
|
||||||
@@ -2764,16 +2764,17 @@ public class BubbleStackView extends FrameLayout
|
|||||||
}
|
}
|
||||||
boolean isOverflowExpanded = mExpandedBubble != null
|
boolean isOverflowExpanded = mExpandedBubble != null
|
||||||
&& BubbleOverflow.KEY.equals(mExpandedBubble.getKey());
|
&& BubbleOverflow.KEY.equals(mExpandedBubble.getKey());
|
||||||
int[] paddings = mPositioner.getExpandedViewPadding(
|
int[] paddings = mPositioner.getExpandedViewContainerPadding(
|
||||||
mStackAnimationController.isStackOnLeftSide(), isOverflowExpanded);
|
mStackAnimationController.isStackOnLeftSide(), isOverflowExpanded);
|
||||||
mExpandedViewContainer.setPadding(paddings[0], paddings[1], paddings[2], paddings[3]);
|
mExpandedViewContainer.setPadding(paddings[0], paddings[1], paddings[2], paddings[3]);
|
||||||
if (mIsExpansionAnimating) {
|
if (mIsExpansionAnimating) {
|
||||||
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
|
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
|
||||||
}
|
}
|
||||||
if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
|
if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
|
||||||
|
PointF p = mPositioner.getExpandedBubbleXY(getBubbleIndex(mExpandedBubble),
|
||||||
|
mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe);
|
||||||
mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY(mExpandedBubble,
|
mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY(mExpandedBubble,
|
||||||
mExpandedAnimationController.getBubbleXOrYForOrientation(
|
mPositioner.showBubblesVertically() ? p.y : p.x));
|
||||||
getBubbleIndex(mExpandedBubble))));
|
|
||||||
mExpandedViewContainer.setTranslationX(0f);
|
mExpandedViewContainer.setTranslationX(0f);
|
||||||
mExpandedBubble.getExpandedView().updateView(
|
mExpandedBubble.getExpandedView().updateView(
|
||||||
mExpandedViewContainer.getLocationOnScreen());
|
mExpandedViewContainer.getLocationOnScreen());
|
||||||
@@ -2856,8 +2857,13 @@ public class BubbleStackView extends FrameLayout
|
|||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float bubblePosition = mExpandedAnimationController.getBubbleXOrYForOrientation(index);
|
PointF bubblePosition = mPositioner.getExpandedBubbleXY(index,
|
||||||
mExpandedBubble.getExpandedView().setPointerPosition(bubblePosition, mStackOnLeftOrWillBe);
|
mBubbleContainer.getChildCount(),
|
||||||
|
mStackOnLeftOrWillBe);
|
||||||
|
mExpandedBubble.getExpandedView().setPointerPosition(mPositioner.showBubblesVertically()
|
||||||
|
? bubblePosition.y
|
||||||
|
: bubblePosition.x,
|
||||||
|
mStackOnLeftOrWillBe);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -76,8 +76,6 @@ public class ExpandedAnimationController
|
|||||||
|
|
||||||
/** Horizontal offset between bubbles, which we need to know to re-stack them. */
|
/** Horizontal offset between bubbles, which we need to know to re-stack them. */
|
||||||
private float mStackOffsetPx;
|
private float mStackOffsetPx;
|
||||||
/** Space between status bar and bubbles in the expanded state. */
|
|
||||||
private float mBubblePaddingTop;
|
|
||||||
/** Size of each bubble. */
|
/** Size of each bubble. */
|
||||||
private float mBubbleSizePx;
|
private float mBubbleSizePx;
|
||||||
/** Whether the expand / collapse animation is running. */
|
/** Whether the expand / collapse animation is running. */
|
||||||
@@ -118,8 +116,6 @@ public class ExpandedAnimationController
|
|||||||
/** The bubble currently being dragged out of the row (to potentially be dismissed). */
|
/** The bubble currently being dragged out of the row (to potentially be dismissed). */
|
||||||
private MagnetizedObject<View> mMagnetizedBubbleDraggingOut;
|
private MagnetizedObject<View> mMagnetizedBubbleDraggingOut;
|
||||||
|
|
||||||
private int mExpandedViewPadding;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to run whenever any bubble is animated out. The BubbleStackView will check if the
|
* Callback to run whenever any bubble is animated out. The BubbleStackView will check if the
|
||||||
* end of this animation means we have no bubbles left, and notify the BubbleController.
|
* end of this animation means we have no bubbles left, and notify the BubbleController.
|
||||||
@@ -128,11 +124,10 @@ public class ExpandedAnimationController
|
|||||||
|
|
||||||
private BubblePositioner mPositioner;
|
private BubblePositioner mPositioner;
|
||||||
|
|
||||||
public ExpandedAnimationController(BubblePositioner positioner, int expandedViewPadding,
|
public ExpandedAnimationController(BubblePositioner positioner,
|
||||||
Runnable onBubbleAnimatedOutAction) {
|
Runnable onBubbleAnimatedOutAction) {
|
||||||
mPositioner = positioner;
|
mPositioner = positioner;
|
||||||
updateResources();
|
updateResources();
|
||||||
mExpandedViewPadding = expandedViewPadding;
|
|
||||||
mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
|
mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
|
||||||
mCollapsePoint = mPositioner.getDefaultStartPosition();
|
mCollapsePoint = mPositioner.getDefaultStartPosition();
|
||||||
}
|
}
|
||||||
@@ -199,7 +194,6 @@ public class ExpandedAnimationController
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Resources res = mLayout.getContext().getResources();
|
Resources res = mLayout.getContext().getResources();
|
||||||
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
|
|
||||||
mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
|
mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
|
||||||
mBubbleSizePx = mPositioner.getBubbleSize();
|
mBubbleSizePx = mPositioner.getBubbleSize();
|
||||||
}
|
}
|
||||||
@@ -245,31 +239,22 @@ public class ExpandedAnimationController
|
|||||||
final Path path = new Path();
|
final Path path = new Path();
|
||||||
path.moveTo(bubble.getTranslationX(), bubble.getTranslationY());
|
path.moveTo(bubble.getTranslationX(), bubble.getTranslationY());
|
||||||
|
|
||||||
final float expandedY = mPositioner.showBubblesVertically()
|
boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint);
|
||||||
? getBubbleXOrYForOrientation(index)
|
final PointF p = mPositioner.getExpandedBubbleXY(index,
|
||||||
: getExpandedY();
|
mLayout.getChildCount(),
|
||||||
|
onLeft);
|
||||||
if (expanding) {
|
if (expanding) {
|
||||||
// If we're expanding, first draw a line from the bubble's current position to the
|
// If we're expanding, first draw a line from the bubble's current position to where
|
||||||
// top of the screen.
|
// it'll end up
|
||||||
path.lineTo(bubble.getTranslationX(), expandedY);
|
path.lineTo(bubble.getTranslationX(), p.y);
|
||||||
// Then, draw a line across the screen to the bubble's resting position.
|
// Then, draw a line across the screen to the bubble's resting position.
|
||||||
if (mPositioner.showBubblesVertically()) {
|
path.lineTo(p.x, p.y);
|
||||||
Rect availableRect = mPositioner.getAvailableRect();
|
|
||||||
boolean onLeft = mCollapsePoint != null
|
|
||||||
&& mCollapsePoint.x < (availableRect.width() / 2f);
|
|
||||||
float translationX = onLeft
|
|
||||||
? availableRect.left
|
|
||||||
: availableRect.right - mBubbleSizePx;
|
|
||||||
path.lineTo(translationX, getBubbleXOrYForOrientation(index));
|
|
||||||
} else {
|
|
||||||
path.lineTo(getBubbleXOrYForOrientation(index), expandedY);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
final float stackedX = mCollapsePoint.x;
|
final float stackedX = mCollapsePoint.x;
|
||||||
|
|
||||||
// If we're collapsing, draw a line from the bubble's current position to the side
|
// If we're collapsing, draw a line from the bubble's current position to the side
|
||||||
// of the screen where the bubble will be stacked.
|
// of the screen where the bubble will be stacked.
|
||||||
path.lineTo(stackedX, expandedY);
|
path.lineTo(stackedX, p.y);
|
||||||
|
|
||||||
// Then, draw a line down to the stack position.
|
// Then, draw a line down to the stack position.
|
||||||
path.lineTo(stackedX, mCollapsePoint.y
|
path.lineTo(stackedX, mCollapsePoint.y
|
||||||
@@ -379,8 +364,9 @@ public class ExpandedAnimationController
|
|||||||
bubbleView.setTranslationY(y);
|
bubbleView.setTranslationY(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final float expandedY = mPositioner.getExpandedBubblesY();
|
||||||
final boolean draggedOutEnough =
|
final boolean draggedOutEnough =
|
||||||
y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx;
|
y > expandedY + mBubbleSizePx || y < expandedY - mBubbleSizePx;
|
||||||
if (draggedOutEnough != mBubbleDraggedOutEnough) {
|
if (draggedOutEnough != mBubbleDraggedOutEnough) {
|
||||||
updateBubblePositions();
|
updateBubblePositions();
|
||||||
mBubbleDraggedOutEnough = draggedOutEnough;
|
mBubbleDraggedOutEnough = draggedOutEnough;
|
||||||
@@ -424,9 +410,10 @@ public class ExpandedAnimationController
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final int index = mLayout.indexOfChild(bubbleView);
|
final int index = mLayout.indexOfChild(bubbleView);
|
||||||
|
final PointF p = mPositioner.getExpandedBubbleXY(index, mLayout.getChildCount(),
|
||||||
|
mPositioner.isStackOnLeft(mCollapsePoint));
|
||||||
animationForChildAtIndex(index)
|
animationForChildAtIndex(index)
|
||||||
.position(getBubbleXOrYForOrientation(index), getExpandedY())
|
.position(p.x, p.y)
|
||||||
.withPositionStartVelocities(velX, velY)
|
.withPositionStartVelocities(velX, velY)
|
||||||
.start(() -> bubbleView.setTranslationZ(0f) /* after */);
|
.start(() -> bubbleView.setTranslationZ(0f) /* after */);
|
||||||
|
|
||||||
@@ -443,17 +430,13 @@ public class ExpandedAnimationController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animates the bubbles to {@link #getExpandedY()} position. Used in response to IME showing.
|
* Animates the bubbles to the y position. Used in response to IME showing.
|
||||||
*/
|
*/
|
||||||
public void updateYPosition(Runnable after) {
|
public void updateYPosition(Runnable after) {
|
||||||
if (mLayout == null) return;
|
if (mLayout == null) return;
|
||||||
animationsForChildrenFromIndex(
|
animationsForChildrenFromIndex(
|
||||||
0, (i, anim) -> anim.translationY(getExpandedY())).startAll(after);
|
0, (i, anim) -> anim.translationY(mPositioner.getExpandedBubblesY()))
|
||||||
}
|
.startAll(after);
|
||||||
|
|
||||||
/** The Y value of the row of expanded bubbles. */
|
|
||||||
public float getExpandedY() {
|
|
||||||
return mPositioner.getAvailableRect().top + mBubblePaddingTop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Description of current animation controller state. */
|
/** Description of current animation controller state. */
|
||||||
@@ -511,35 +494,36 @@ public class ExpandedAnimationController
|
|||||||
startOrUpdatePathAnimation(true /* expanding */);
|
startOrUpdatePathAnimation(true /* expanding */);
|
||||||
} else if (mAnimatingCollapse) {
|
} else if (mAnimatingCollapse) {
|
||||||
startOrUpdatePathAnimation(false /* expanding */);
|
startOrUpdatePathAnimation(false /* expanding */);
|
||||||
} else if (mPositioner.showBubblesVertically()) {
|
} else {
|
||||||
child.setTranslationY(getBubbleXOrYForOrientation(index));
|
boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint);
|
||||||
|
final PointF p = mPositioner.getExpandedBubbleXY(index,
|
||||||
|
mLayout.getChildCount(),
|
||||||
|
onLeft);
|
||||||
|
if (mPositioner.showBubblesVertically()) {
|
||||||
|
child.setTranslationY(p.y);
|
||||||
|
} else {
|
||||||
|
child.setTranslationX(p.x);
|
||||||
|
}
|
||||||
if (!mPreparingToCollapse) {
|
if (!mPreparingToCollapse) {
|
||||||
// Only animate if we're not collapsing as that animation will handle placing the
|
// Only animate if we're not collapsing as that animation will handle placing the
|
||||||
// new bubble in the stacked position.
|
// new bubble in the stacked position.
|
||||||
|
if (mPositioner.showBubblesVertically()) {
|
||||||
Rect availableRect = mPositioner.getAvailableRect();
|
Rect availableRect = mPositioner.getAvailableRect();
|
||||||
boolean onLeft = mCollapsePoint != null
|
|
||||||
&& mCollapsePoint.x < (availableRect.width() / 2f);
|
|
||||||
float fromX = onLeft
|
float fromX = onLeft
|
||||||
? -mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR
|
? -mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR
|
||||||
: availableRect.right + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR;
|
: availableRect.right + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR;
|
||||||
float toX = onLeft
|
|
||||||
? availableRect.left + mExpandedViewPadding
|
|
||||||
: availableRect.right - mBubbleSizePx - mExpandedViewPadding;
|
|
||||||
animationForChild(child)
|
animationForChild(child)
|
||||||
.translationX(fromX, toX)
|
.translationX(fromX, p.y)
|
||||||
.start();
|
.start();
|
||||||
updateBubblePositions();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
child.setTranslationX(getBubbleXOrYForOrientation(index));
|
// Only animate if we're not collapsing as that animation will handle placing
|
||||||
if (!mPreparingToCollapse) {
|
// the new bubble in the stacked position.
|
||||||
// Only animate if we're not collapsing as that animation will handle placing the
|
float fromY = mPositioner.getExpandedBubblesY() - mBubbleSizePx
|
||||||
// new bubble in the stacked position.
|
* ANIMATE_TRANSLATION_FACTOR;
|
||||||
float toY = getExpandedY();
|
|
||||||
float fromY = getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR;
|
|
||||||
animationForChild(child)
|
animationForChild(child)
|
||||||
.translationY(fromY, toY)
|
.translationY(fromY, p.y)
|
||||||
.start();
|
.start();
|
||||||
|
}
|
||||||
updateBubblePositions();
|
updateBubblePositions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -588,7 +572,7 @@ public class ExpandedAnimationController
|
|||||||
if (mAnimatingExpand || mAnimatingCollapse) {
|
if (mAnimatingExpand || mAnimatingCollapse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint);
|
||||||
for (int i = 0; i < mLayout.getChildCount(); i++) {
|
for (int i = 0; i < mLayout.getChildCount(); i++) {
|
||||||
final View bubble = mLayout.getChildAt(i);
|
final View bubble = mLayout.getChildAt(i);
|
||||||
|
|
||||||
@@ -598,39 +582,11 @@ public class ExpandedAnimationController
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPositioner.showBubblesVertically()) {
|
final PointF p = mPositioner.getExpandedBubbleXY(i, mLayout.getChildCount(), onLeft);
|
||||||
Rect availableRect = mPositioner.getAvailableRect();
|
|
||||||
boolean onLeft = mCollapsePoint != null
|
|
||||||
&& mCollapsePoint.x < (availableRect.width() / 2f);
|
|
||||||
animationForChild(bubble)
|
animationForChild(bubble)
|
||||||
.translationX(onLeft
|
.translationX(p.x)
|
||||||
? availableRect.left
|
.translationY(p.y)
|
||||||
: availableRect.right - mBubbleSizePx)
|
|
||||||
.translationY(getBubbleXOrYForOrientation(i))
|
|
||||||
.start();
|
|
||||||
} else {
|
|
||||||
animationForChild(bubble)
|
|
||||||
.translationX(getBubbleXOrYForOrientation(i))
|
|
||||||
.translationY(getExpandedY())
|
|
||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
* @return the y position of the bubble if showing vertically and the x position if showing
|
|
||||||
* horizontally.
|
|
||||||
*/
|
|
||||||
public float getBubbleXOrYForOrientation(int index) {
|
|
||||||
if (mLayout == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return mPositioner.getBubbleXOrYForOrientation(index, mLayout.getChildCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -305,10 +305,7 @@ public class StackAnimationController extends
|
|||||||
if (mLayout == null || !isStackPositionSet()) {
|
if (mLayout == null || !isStackPositionSet()) {
|
||||||
return true; // Default to left, which is where it starts by default.
|
return true; // Default to left, which is where it starts by default.
|
||||||
}
|
}
|
||||||
|
return mPositioner.isStackOnLeft(mStackPosition);
|
||||||
float stackCenter = mStackPosition.x + mBubbleSize / 2;
|
|
||||||
float screenCenter = mLayout.getWidth() / 2;
|
|
||||||
return stackCenter < screenCenter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.wm.shell.bubbles.animation;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
@@ -41,7 +42,6 @@ import org.junit.Before;
|
|||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Spy;
|
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
@@ -49,26 +49,26 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
|
|||||||
|
|
||||||
private int mDisplayWidth = 500;
|
private int mDisplayWidth = 500;
|
||||||
private int mDisplayHeight = 1000;
|
private int mDisplayHeight = 1000;
|
||||||
private int mExpandedViewPadding = 10;
|
|
||||||
|
|
||||||
private Runnable mOnBubbleAnimatedOutAction = mock(Runnable.class);
|
private Runnable mOnBubbleAnimatedOutAction = mock(Runnable.class);
|
||||||
@Spy
|
|
||||||
ExpandedAnimationController mExpandedController;
|
ExpandedAnimationController mExpandedController;
|
||||||
|
|
||||||
private int mStackOffset;
|
private int mStackOffset;
|
||||||
private PointF mExpansionPoint;
|
private PointF mExpansionPoint;
|
||||||
|
private BubblePositioner mPositioner;
|
||||||
|
|
||||||
@SuppressLint("VisibleForTests")
|
@SuppressLint("VisibleForTests")
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
BubblePositioner positioner = new BubblePositioner(getContext(), mock(WindowManager.class));
|
mPositioner = new BubblePositioner(getContext(), mock(WindowManager.class));
|
||||||
positioner.updateInternal(Configuration.ORIENTATION_PORTRAIT,
|
mPositioner.updateInternal(Configuration.ORIENTATION_PORTRAIT,
|
||||||
Insets.of(0, 0, 0, 0),
|
Insets.of(0, 0, 0, 0),
|
||||||
new Rect(0, 0, mDisplayWidth, mDisplayHeight));
|
new Rect(0, 0, mDisplayWidth, mDisplayHeight));
|
||||||
mExpandedController = new ExpandedAnimationController(positioner, mExpandedViewPadding,
|
mExpandedController = new ExpandedAnimationController(mPositioner,
|
||||||
mOnBubbleAnimatedOutAction);
|
mOnBubbleAnimatedOutAction);
|
||||||
|
spyOn(mExpandedController);
|
||||||
|
|
||||||
addOneMoreThanBubbleLimitBubbles();
|
addOneMoreThanBubbleLimitBubbles();
|
||||||
mLayout.setActiveController(mExpandedController);
|
mLayout.setActiveController(mExpandedController);
|
||||||
@@ -141,13 +141,16 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
|
|||||||
|
|
||||||
/** Check that children are in the correct positions for being expanded. */
|
/** Check that children are in the correct positions for being expanded. */
|
||||||
private void testBubblesInCorrectExpandedPositions() {
|
private void testBubblesInCorrectExpandedPositions() {
|
||||||
|
boolean onLeft = mPositioner.isStackOnLeft(mExpansionPoint);
|
||||||
// Check all the visible bubbles to see if they're in the right place.
|
// Check all the visible bubbles to see if they're in the right place.
|
||||||
for (int i = 0; i < mLayout.getChildCount(); i++) {
|
for (int i = 0; i < mLayout.getChildCount(); i++) {
|
||||||
float expectedPosition = mExpandedController.getBubbleXOrYForOrientation(i);
|
PointF expectedPosition = mPositioner.getExpandedBubbleXY(i,
|
||||||
assertEquals(expectedPosition,
|
mLayout.getChildCount(),
|
||||||
|
onLeft);
|
||||||
|
assertEquals(expectedPosition.x,
|
||||||
mLayout.getChildAt(i).getTranslationX(),
|
mLayout.getChildAt(i).getTranslationX(),
|
||||||
2f);
|
2f);
|
||||||
assertEquals(expectedPosition,
|
assertEquals(expectedPosition.y,
|
||||||
mLayout.getChildAt(i).getTranslationY(), 2f);
|
mLayout.getChildAt(i).getTranslationY(), 2f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user