Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aad97318 authored by Mady Mellor's avatar Mady Mellor Committed by Automerger Merge Worker
Browse files

Merge "Center bubbles horizontally on large screens" into sc-v2-dev am: af3974cb

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15503049

Change-Id: I3b4d0fa6675484b3c4e7b5a4a36a33e44c453eaa
parents d466613e af3974cb
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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);

+118 −53
Original line number Diff line number Diff line
@@ -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,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.
     * 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) {
    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 boolean isLargeOrOverflow = mIsLargeScreen || isOverflow;
            final float expandedViewWidth = isOverflow
                    ? mOverflowWidth
                    : mExpandedViewLargeScreenWidth;
            if (showBubblesVertically()) {
                if (!onLeft) {
                rightPadding += mBubbleSize - mPointerHeight;
                leftPadding += isLargeOrOverflow
                    rightPadding += mBubbleSize - pointerTotalHeight;
                    leftPadding += isOverflow
                            ? (mPositionRect.width() - rightPadding - expandedViewWidth)
                            : 0;
                } else {
                leftPadding += mBubbleSize - mPointerHeight;
                rightPadding += isLargeOrOverflow
                    leftPadding += mBubbleSize - pointerTotalHeight;
                    rightPadding += isOverflow
                            ? (mPositionRect.width() - leftPadding - expandedViewWidth)
                            : 0;
                }
@@ -326,34 +354,42 @@ public class BubblePositioner {
            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.
+47 −41
Original line number Diff line number Diff line
@@ -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);
    }

    /**
+50 −94

File changed.

Preview size limit exceeded, changes collapsed.

+1 −4
Original line number Diff line number Diff line
@@ -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);
    }

    /**
Loading