diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index 4ac7dcf3d23a1..7d7bfb2a92a33 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -696,8 +696,10 @@ public class BubbleExpandedView extends LinearLayout { ? mPointerHeight - mPointerOverlap : 0; final float paddingRight = (showVertically && !onLeft) - ? mPointerHeight - mPointerOverlap : 0; - final float paddingTop = showVertically ? 0 + ? mPointerHeight - mPointerOverlap + : 0; + final float paddingTop = showVertically + ? 0 : mPointerHeight - mPointerOverlap; setPadding((int) paddingLeft, (int) paddingTop, (int) paddingRight, 0); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java index 7d4fb21584c76..306224bd316c8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java @@ -79,14 +79,18 @@ public class BubblePositioner { private int mBubbleSize; private int mSpacingBetweenBubbles; - private float mExpandedViewLargeScreenWidth; + + private int mExpandedViewMinHeight; + private int mExpandedViewLargeScreenWidth; + private int mExpandedViewLargeScreenInset; + private int mOverflowWidth; private int mExpandedViewPadding; private int mPointerMargin; private int mPointerWidth; private int mPointerHeight; + private int mPointerOverlap; private int mManageButtonHeight; - private int mExpandedViewMinHeight; private int mOverflowHeight; private int mMinimumFlyoutWidthLargeScreen; @@ -168,15 +172,20 @@ public class BubblePositioner { mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size); mSpacingBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing); 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 - ? (int) mExpandedViewLargeScreenWidth + ? mExpandedViewLargeScreenWidth : res.getDimensionPixelSize( 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); 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_total_height); mExpandedViewMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height); mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height); @@ -294,66 +303,93 @@ 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. - * On landscape the bubble overflow expanded view is also restricted via this padding. + * Some specifics: + * 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) { - int leftPadding = mInsets.left + mExpandedViewPadding; - int rightPadding = mInsets.right + mExpandedViewPadding; - final boolean isLargeOrOverflow = mIsLargeScreen || isOverflow; - final float expandedViewWidth = isOverflow - ? mOverflowWidth - : mExpandedViewLargeScreenWidth; - if (showBubblesVertically()) { - if (!onLeft) { - rightPadding += mBubbleSize - mPointerHeight; - leftPadding += isLargeOrOverflow - ? (mPositionRect.width() - rightPadding - expandedViewWidth) - : 0; - } else { - leftPadding += mBubbleSize - mPointerHeight; - rightPadding += isLargeOrOverflow - ? (mPositionRect.width() - leftPadding - expandedViewWidth) - : 0; + 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 rightPadding = mInsets.right + mExpandedViewPadding; + final float expandedViewWidth = isOverflow + ? mOverflowWidth + : mExpandedViewLargeScreenWidth; + if (showBubblesVertically()) { + if (!onLeft) { + rightPadding += mBubbleSize - pointerTotalHeight; + leftPadding += isOverflow + ? (mPositionRect.width() - rightPadding - expandedViewWidth) + : 0; + } else { + leftPadding += mBubbleSize - pointerTotalHeight; + rightPadding += isOverflow + ? (mPositionRect.width() - leftPadding - expandedViewWidth) + : 0; + } } + // [left, top, right, bottom] + mPaddings[0] = leftPadding; + mPaddings[1] = showBubblesVertically() ? 0 : mPointerMargin; + mPaddings[2] = rightPadding; + mPaddings[3] = 0; + return mPaddings; } - // [left, top, right, bottom] - mPaddings[0] = leftPadding; - mPaddings[1] = showBubblesVertically() ? 0 : mPointerMargin; - mPaddings[2] = rightPadding; - mPaddings[3] = 0; - return mPaddings; } /** 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; + return top - mPointerWidth + mExpandedViewPadding; } else { 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) { + // Subtract top insets because availableRect.height would account for that + int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top; 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; + int bottomPadding = isOverflow ? mExpandedViewPadding : mManageButtonHeight; return getAvailableRect().height() - expandedContainerY - paddingTop - - settingsHeight - - pointerSize; + - pointerSize + - bottomPadding; } /** @@ -362,11 +398,14 @@ public class BubblePositioner { */ public float getExpandedViewHeight(BubbleViewProvider bubble) { 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 ? mOverflowHeight : ((Bubble) bubble).getDesiredHeight(mContext); - int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight; - desiredHeight = Math.max(manageButtonHeight + desiredHeight, mExpandedViewMinHeight); + desiredHeight = Math.max(desiredHeight, mExpandedViewMinHeight); if (desiredHeight > getMaxExpandedViewHeight(isOverflow)) { return MAX_HEIGHT; } @@ -391,7 +430,7 @@ public class BubblePositioner { return topAlignment; } // 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 bottomIfCentered = pointerPosition + (expandedViewHeight / 2) + manageButtonHeight; 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 - * 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. + * Returns the position of the bubble on-screen when the stack is expanded. * - * @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. + * @param index the index of the bubble in the stack. + * @param numberOfBubbles the total number of bubbles in the stack. + * @param onLeftEdge whether the stack would rest on the left edge of the screen when collapsed. + * @return the x, y position of the bubble on-screen when the stack is expanded. */ - public float getBubbleXOrYForOrientation(int index, int numberOfBubbles) { - final float positionInBar = index * (mBubbleSize + mSpacingBetweenBubbles); + public PointF getExpandedBubbleXY(int index, int numberOfBubbles, boolean onLeftEdge) { + final float positionInRow = index * (mBubbleSize + mSpacingBetweenBubbles); final float expandedStackSize = (numberOfBubbles * mBubbleSize) + ((numberOfBubbles - 1) * mSpacingBetweenBubbles); final float centerPosition = showBubblesVertically() ? mPositionRect.centerY() : mPositionRect.centerX(); + // alignment - centered on the edge 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 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 * last bubble is removed, so that the stack can be restored in its previous position. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 3d2505ef76999..5a51eed04e1a1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -778,8 +778,8 @@ public class BubbleStackView extends FrameLayout floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut, this::animateShadows /* onStackAnimationFinished */, mPositioner); - mExpandedAnimationController = new ExpandedAnimationController( - mPositioner, mExpandedViewPadding, onBubbleAnimatedOut); + mExpandedAnimationController = new ExpandedAnimationController(mPositioner, + onBubbleAnimatedOut); mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER; // 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(); } } /* after */); - - final float translationY = mPositioner.getExpandedViewY(mExpandedBubble, - getBubbleIndex(mExpandedBubble)); - mExpandedViewContainer.setTranslationX(0f); - mExpandedViewContainer.setTranslationY(translationY); - mExpandedViewContainer.setAlpha(1f); - int index; if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) { index = mBubbleData.getBubbles().size(); } else { index = getBubbleIndex(mExpandedBubble); } - // Position of the bubble we're expanding, once it's settled in its row. - final float bubbleWillBeAt = - mExpandedAnimationController.getBubbleXOrYForOrientation(index); + PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleContainer.getChildCount(), + mStackOnLeftOrWillBe); + 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 // that are animating farther, so that the expanded view doesn't move as much. final float relevantStackPosition = showVertically ? mStackAnimationController.getStackPosition().y : mStackAnimationController.getStackPosition().x; + final float bubbleWillBeAt = showVertically + ? p.y + : p.x; 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 @@ -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. if (showVertically) { float pivotX; - float pivotY = bubbleWillBeAt + mBubbleSize / 2f; if (mStackOnLeftOrWillBe) { - pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding; + pivotX = p.x + mBubbleSize + mExpandedViewPadding; } else { - pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding; + pivotX = p.x - mExpandedViewPadding; } mExpandedViewContainerMatrix.setScale( 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT, 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT, - pivotX, pivotY); + pivotX, + p.y + mBubbleSize / 2f); } else { mExpandedViewContainerMatrix.setScale( 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT, 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT, - bubbleWillBeAt + mBubbleSize / 2f, - translationY); + p.x + mBubbleSize / 2f, + p.y + mBubbleSize + mExpandedViewPadding); } mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix); @@ -1959,6 +1959,7 @@ public class BubbleStackView extends FrameLayout mExpandedViewContainerMatrix); }) .withEndActions(() -> { + mExpandedViewContainer.setAnimationMatrix(null); afterExpandedViewAnimation(); if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) { @@ -2009,12 +2010,11 @@ public class BubbleStackView extends FrameLayout index = mBubbleData.getBubbles().indexOf(mExpandedBubble); } // Value the bubble is animating from (back into the stack). - final float expandingFromBubbleAt = - mExpandedAnimationController.getBubbleXOrYForOrientation(index); - final boolean showVertically = mPositioner.showBubblesVertically(); + final PointF p = mPositioner.getExpandedBubbleXY(index, + mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe); if (mPositioner.showBubblesVertically()) { float pivotX; - float pivotY = expandingFromBubbleAt + mBubbleSize / 2f; + float pivotY = p.y + mBubbleSize / 2f; if (mStackOnLeftOrWillBe) { pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding; } else { @@ -2026,8 +2026,8 @@ public class BubbleStackView extends FrameLayout } else { mExpandedViewContainerMatrix.setScale( 1f, 1f, - expandingFromBubbleAt + mBubbleSize / 2f, - mPositioner.getExpandedViewY(mExpandedBubble, index)); + p.x + mBubbleSize / 2f, + p.y + mBubbleSize + mExpandedViewPadding); } mExpandedViewAlphaAnimator.reverse(); @@ -2105,32 +2105,31 @@ public class BubbleStackView extends FrameLayout boolean isOverflow = mExpandedBubble != null && mExpandedBubble.getKey().equals(BubbleOverflow.KEY); - float expandingFromBubbleDestination = - mExpandedAnimationController.getBubbleXOrYForOrientation(isOverflow - ? getBubbleCount() - : mBubbleData.getBubbles().indexOf(mExpandedBubble)); - + PointF p = mPositioner.getExpandedBubbleXY(isOverflow + ? mBubbleContainer.getChildCount() - 1 + : mBubbleData.getBubbles().indexOf(mExpandedBubble), + mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe); mExpandedViewContainer.setAlpha(1f); mExpandedViewContainer.setVisibility(View.VISIBLE); if (mPositioner.showBubblesVertically()) { float pivotX; - float pivotY = expandingFromBubbleDestination + mBubbleSize / 2f; + float pivotY = p.y + mBubbleSize / 2f; if (mStackOnLeftOrWillBe) { - pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding; + pivotX = p.x + mBubbleSize + mExpandedViewPadding; } else { - pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding; - + pivotX = p.x - mExpandedViewPadding; } mExpandedViewContainerMatrix.setScale( - 0f, 0f, + 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT, + 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT, pivotX, pivotY); } else { mExpandedViewContainerMatrix.setScale( 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT, 1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT, - expandingFromBubbleDestination + mBubbleSize / 2f, - mPositioner.getExpandedViewY(mExpandedBubble, expandingFromBubbleDestination)); + p.x + mBubbleSize / 2f, + p.y + mBubbleSize + mExpandedViewPadding); } mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix); @@ -2155,6 +2154,7 @@ public class BubbleStackView extends FrameLayout .withEndActions(() -> { mExpandedViewTemporarilyHidden = false; mIsBubbleSwitchAnimating = false; + mExpandedViewContainer.setAnimationMatrix(null); }) .start(); }, 25); @@ -2764,16 +2764,17 @@ public class BubbleStackView extends FrameLayout } boolean isOverflowExpanded = mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey()); - int[] paddings = mPositioner.getExpandedViewPadding( + int[] paddings = mPositioner.getExpandedViewContainerPadding( mStackAnimationController.isStackOnLeftSide(), isOverflowExpanded); mExpandedViewContainer.setPadding(paddings[0], paddings[1], paddings[2], paddings[3]); if (mIsExpansionAnimating) { mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE); } if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) { + PointF p = mPositioner.getExpandedBubbleXY(getBubbleIndex(mExpandedBubble), + mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe); mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY(mExpandedBubble, - mExpandedAnimationController.getBubbleXOrYForOrientation( - getBubbleIndex(mExpandedBubble)))); + mPositioner.showBubblesVertically() ? p.y : p.x)); mExpandedViewContainer.setTranslationX(0f); mExpandedBubble.getExpandedView().updateView( mExpandedViewContainer.getLocationOnScreen()); @@ -2856,8 +2857,13 @@ public class BubbleStackView extends FrameLayout if (index == -1) { return; } - float bubblePosition = mExpandedAnimationController.getBubbleXOrYForOrientation(index); - mExpandedBubble.getExpandedView().setPointerPosition(bubblePosition, mStackOnLeftOrWillBe); + PointF bubblePosition = mPositioner.getExpandedBubbleXY(index, + mBubbleContainer.getChildCount(), + mStackOnLeftOrWillBe); + mExpandedBubble.getExpandedView().setPointerPosition(mPositioner.showBubblesVertically() + ? bubblePosition.y + : bubblePosition.x, + mStackOnLeftOrWillBe); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java index 007ddbf631416..c32be98866cf7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java @@ -76,8 +76,6 @@ public class ExpandedAnimationController /** Horizontal offset between bubbles, which we need to know to re-stack them. */ private float mStackOffsetPx; - /** Space between status bar and bubbles in the expanded state. */ - private float mBubblePaddingTop; /** Size of each bubble. */ private float mBubbleSizePx; /** 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). */ private MagnetizedObject mMagnetizedBubbleDraggingOut; - private int mExpandedViewPadding; - /** * 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. @@ -128,11 +124,10 @@ public class ExpandedAnimationController private BubblePositioner mPositioner; - public ExpandedAnimationController(BubblePositioner positioner, int expandedViewPadding, + public ExpandedAnimationController(BubblePositioner positioner, Runnable onBubbleAnimatedOutAction) { mPositioner = positioner; updateResources(); - mExpandedViewPadding = expandedViewPadding; mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction; mCollapsePoint = mPositioner.getDefaultStartPosition(); } @@ -199,7 +194,6 @@ public class ExpandedAnimationController return; } Resources res = mLayout.getContext().getResources(); - mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top); mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset); mBubbleSizePx = mPositioner.getBubbleSize(); } @@ -245,31 +239,22 @@ public class ExpandedAnimationController final Path path = new Path(); path.moveTo(bubble.getTranslationX(), bubble.getTranslationY()); - final float expandedY = mPositioner.showBubblesVertically() - ? getBubbleXOrYForOrientation(index) - : getExpandedY(); + boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint); + final PointF p = mPositioner.getExpandedBubbleXY(index, + mLayout.getChildCount(), + onLeft); if (expanding) { - // If we're expanding, first draw a line from the bubble's current position to the - // top of the screen. - path.lineTo(bubble.getTranslationX(), expandedY); + // If we're expanding, first draw a line from the bubble's current position to where + // it'll end up + path.lineTo(bubble.getTranslationX(), p.y); // Then, draw a line across the screen to the bubble's resting position. - if (mPositioner.showBubblesVertically()) { - 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); - } + path.lineTo(p.x, p.y); } else { final float stackedX = mCollapsePoint.x; // 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. - path.lineTo(stackedX, expandedY); + path.lineTo(stackedX, p.y); // Then, draw a line down to the stack position. path.lineTo(stackedX, mCollapsePoint.y @@ -379,8 +364,9 @@ public class ExpandedAnimationController bubbleView.setTranslationY(y); } + final float expandedY = mPositioner.getExpandedBubblesY(); final boolean draggedOutEnough = - y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx; + y > expandedY + mBubbleSizePx || y < expandedY - mBubbleSizePx; if (draggedOutEnough != mBubbleDraggedOutEnough) { updateBubblePositions(); mBubbleDraggedOutEnough = draggedOutEnough; @@ -424,9 +410,10 @@ public class ExpandedAnimationController return; } final int index = mLayout.indexOfChild(bubbleView); - + final PointF p = mPositioner.getExpandedBubbleXY(index, mLayout.getChildCount(), + mPositioner.isStackOnLeft(mCollapsePoint)); animationForChildAtIndex(index) - .position(getBubbleXOrYForOrientation(index), getExpandedY()) + .position(p.x, p.y) .withPositionStartVelocities(velX, velY) .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) { if (mLayout == null) return; animationsForChildrenFromIndex( - 0, (i, anim) -> anim.translationY(getExpandedY())).startAll(after); - } - - /** The Y value of the row of expanded bubbles. */ - public float getExpandedY() { - return mPositioner.getAvailableRect().top + mBubblePaddingTop; + 0, (i, anim) -> anim.translationY(mPositioner.getExpandedBubblesY())) + .startAll(after); } /** Description of current animation controller state. */ @@ -511,35 +494,36 @@ public class ExpandedAnimationController startOrUpdatePathAnimation(true /* expanding */); } else if (mAnimatingCollapse) { startOrUpdatePathAnimation(false /* expanding */); - } else if (mPositioner.showBubblesVertically()) { - child.setTranslationY(getBubbleXOrYForOrientation(index)); - if (!mPreparingToCollapse) { - // Only animate if we're not collapsing as that animation will handle placing the - // new bubble in the stacked position. - Rect availableRect = mPositioner.getAvailableRect(); - boolean onLeft = mCollapsePoint != null - && mCollapsePoint.x < (availableRect.width() / 2f); - float fromX = onLeft - ? -mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR - : availableRect.right + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR; - float toX = onLeft - ? availableRect.left + mExpandedViewPadding - : availableRect.right - mBubbleSizePx - mExpandedViewPadding; - animationForChild(child) - .translationX(fromX, toX) - .start(); - updateBubblePositions(); - } } else { - child.setTranslationX(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) { // Only animate if we're not collapsing as that animation will handle placing the // new bubble in the stacked position. - float toY = getExpandedY(); - float fromY = getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR; - animationForChild(child) - .translationY(fromY, toY) - .start(); + if (mPositioner.showBubblesVertically()) { + Rect availableRect = mPositioner.getAvailableRect(); + float fromX = onLeft + ? -mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR + : availableRect.right + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR; + animationForChild(child) + .translationX(fromX, p.y) + .start(); + } else { + // Only animate if we're not collapsing as that animation will handle placing + // the new bubble in the stacked position. + float fromY = mPositioner.getExpandedBubblesY() - mBubbleSizePx + * ANIMATE_TRANSLATION_FACTOR; + animationForChild(child) + .translationY(fromY, p.y) + .start(); + } updateBubblePositions(); } } @@ -588,7 +572,7 @@ public class ExpandedAnimationController if (mAnimatingExpand || mAnimatingCollapse) { return; } - + boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint); for (int i = 0; i < mLayout.getChildCount(); i++) { final View bubble = mLayout.getChildAt(i); @@ -598,39 +582,11 @@ public class ExpandedAnimationController return; } - if (mPositioner.showBubblesVertically()) { - Rect availableRect = mPositioner.getAvailableRect(); - boolean onLeft = mCollapsePoint != null - && mCollapsePoint.x < (availableRect.width() / 2f); - animationForChild(bubble) - .translationX(onLeft - ? availableRect.left - : availableRect.right - mBubbleSizePx) - .translationY(getBubbleXOrYForOrientation(i)) - .start(); - } else { - animationForChild(bubble) - .translationX(getBubbleXOrYForOrientation(i)) - .translationY(getExpandedY()) - .start(); - } + final PointF p = mPositioner.getExpandedBubbleXY(i, mLayout.getChildCount(), onLeft); + animationForChild(bubble) + .translationX(p.x) + .translationY(p.y) + .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()); - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java index 636e1452aa9b9..9a08190675b63 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java @@ -305,10 +305,7 @@ public class StackAnimationController extends if (mLayout == null || !isStackPositionSet()) { return true; // Default to left, which is where it starts by default. } - - float stackCenter = mStackPosition.x + mBubbleSize / 2; - float screenCenter = mLayout.getWidth() / 2; - return stackCenter < screenCenter; + return mPositioner.isStackOnLeft(mStackPosition); } /** diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java index 1eba3c266358e..9732a8890e0ef 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java @@ -19,6 +19,7 @@ package com.android.wm.shell.bubbles.animation; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import android.annotation.SuppressLint; import android.content.res.Configuration; @@ -41,7 +42,6 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Spy; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -49,26 +49,26 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC private int mDisplayWidth = 500; private int mDisplayHeight = 1000; - private int mExpandedViewPadding = 10; private Runnable mOnBubbleAnimatedOutAction = mock(Runnable.class); - @Spy ExpandedAnimationController mExpandedController; private int mStackOffset; private PointF mExpansionPoint; + private BubblePositioner mPositioner; @SuppressLint("VisibleForTests") @Before public void setUp() throws Exception { super.setUp(); - BubblePositioner positioner = new BubblePositioner(getContext(), mock(WindowManager.class)); - positioner.updateInternal(Configuration.ORIENTATION_PORTRAIT, + mPositioner = new BubblePositioner(getContext(), mock(WindowManager.class)); + mPositioner.updateInternal(Configuration.ORIENTATION_PORTRAIT, Insets.of(0, 0, 0, 0), new Rect(0, 0, mDisplayWidth, mDisplayHeight)); - mExpandedController = new ExpandedAnimationController(positioner, mExpandedViewPadding, + mExpandedController = new ExpandedAnimationController(mPositioner, mOnBubbleAnimatedOutAction); + spyOn(mExpandedController); addOneMoreThanBubbleLimitBubbles(); mLayout.setActiveController(mExpandedController); @@ -141,13 +141,16 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC /** Check that children are in the correct positions for being expanded. */ private void testBubblesInCorrectExpandedPositions() { + boolean onLeft = mPositioner.isStackOnLeft(mExpansionPoint); // Check all the visible bubbles to see if they're in the right place. for (int i = 0; i < mLayout.getChildCount(); i++) { - float expectedPosition = mExpandedController.getBubbleXOrYForOrientation(i); - assertEquals(expectedPosition, + PointF expectedPosition = mPositioner.getExpandedBubbleXY(i, + mLayout.getChildCount(), + onLeft); + assertEquals(expectedPosition.x, mLayout.getChildAt(i).getTranslationX(), 2f); - assertEquals(expectedPosition, + assertEquals(expectedPosition.y, mLayout.getChildAt(i).getTranslationY(), 2f); } }