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

Commit cc312e10 authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge "Ensure the bubble expanded view aligns with the pointer" into sc-v2-dev

parents 7f4daba8 cd2eed4f
Loading
Loading
Loading
Loading
+11 −41
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.wm.shell.bubbles.BubblePositioner.MAX_HEIGHT;

import android.annotation.NonNull;
import android.annotation.SuppressLint;
@@ -60,7 +61,6 @@ import android.widget.LinearLayout;
import androidx.annotation.Nullable;

import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.launcher3.icons.IconNormalizer;
import com.android.wm.shell.R;
import com.android.wm.shell.TaskView;
import com.android.wm.shell.common.AlphaOptimizedButton;
@@ -77,7 +77,6 @@ public class BubbleExpandedView extends LinearLayout {

    // The triangle pointing to the expanded view
    private View mPointerView;
    private int mPointerMargin;
    @Nullable private int[] mExpandedViewContainerLocation;

    private AlphaOptimizedButton mManageButton;
@@ -102,9 +101,6 @@ public class BubbleExpandedView extends LinearLayout {
     */
    private boolean mIsAlphaAnimating = false;

    private int mMinHeight;
    private int mOverflowHeight;
    private int mManageButtonHeight;
    private int mPointerWidth;
    private int mPointerHeight;
    private float mPointerRadius;
@@ -348,12 +344,8 @@ public class BubbleExpandedView extends LinearLayout {

    void updateDimensions() {
        Resources res = getResources();
        mMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
        mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);

        updateFontSize();

        mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
        mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
        mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
        mPointerRadius = getResources().getDimensionPixelSize(R.dimen.bubble_pointer_radius);
@@ -369,7 +361,6 @@ public class BubbleExpandedView extends LinearLayout {
            updatePointerView();
        }

        mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_height);
        if (mManageButton != null) {
            int visibility = mManageButton.getVisibility();
            removeView(mManageButton);
@@ -633,12 +624,11 @@ public class BubbleExpandedView extends LinearLayout {
        }

        if ((mBubble != null && mTaskView != null) || mIsOverflow) {
            float desiredHeight = mIsOverflow
                    ? mPositioner.isLargeScreen() ? getMaxExpandedHeight() : mOverflowHeight
                    : mBubble.getDesiredHeight(mContext);
            desiredHeight = Math.max(desiredHeight, mMinHeight);
            float height = Math.min(desiredHeight, getMaxExpandedHeight());
            height = Math.max(height, mMinHeight);
            float desiredHeight = mPositioner.getExpandedViewHeight(mBubble);
            int maxHeight = mPositioner.getMaxExpandedViewHeight(mIsOverflow);
            float height = desiredHeight == MAX_HEIGHT
                    ? maxHeight
                    : Math.min(desiredHeight, maxHeight);
            FrameLayout.LayoutParams lp = mIsOverflow
                    ? (FrameLayout.LayoutParams) mOverflowView.getLayoutParams()
                    : (FrameLayout.LayoutParams) mTaskView.getLayoutParams();
@@ -662,23 +652,6 @@ public class BubbleExpandedView extends LinearLayout {
        }
    }

    private int getMaxExpandedHeight() {
        int expandedContainerY = mExpandedViewContainerLocation != null
                // Remove top insets back here because availableRect.height would account for that
                ? mExpandedViewContainerLocation[1] - mPositioner.getInsets().top
                : 0;
        int settingsHeight = mIsOverflow ? 0 : mManageButtonHeight;
        int pointerHeight = mPositioner.showBubblesVertically()
                ? mPointerWidth
                : (int) (mPointerHeight - mPointerOverlap + mPointerMargin);
        return mPositioner.getAvailableRect().height()
                - expandedContainerY
                - getPaddingTop()
                - getPaddingBottom()
                - settingsHeight
                - pointerHeight;
    }

    /**
     * Update appearance of the expanded view being displayed.
     *
@@ -728,14 +701,11 @@ public class BubbleExpandedView extends LinearLayout {
                : mPointerHeight - mPointerOverlap;
        setPadding((int) paddingLeft, (int) paddingTop, (int) paddingRight, 0);

        final float expandedViewY = mPositioner.getExpandedViewY();
        // TODO: I don't understand why it works but it does - why normalized in portrait
        //  & not in landscape? Am I missing ~2dp in the portrait expandedViewY calculation?
        final float normalizedSize = IconNormalizer.getNormalizedCircleSize(
                mPositioner.getBubbleSize());
        final float bubbleCenter = showVertically
                ? bubblePosition + (mPositioner.getBubbleSize() / 2f) - expandedViewY
                : bubblePosition + (normalizedSize / 2f) - mPointerWidth;
        // Subtract the expandedViewY here because the pointer is placed within the expandedView.
        float pointerPosition = mPositioner.getPointerPosition(bubblePosition);
        final float bubbleCenter = mPositioner.showBubblesVertically()
                ? pointerPosition - mPositioner.getExpandedViewY(mBubble, bubblePosition)
                : pointerPosition;
        // Post because we need the width of the view
        post(() -> {
            float pointerY;
+125 −6
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.view.WindowMetrics;

import androidx.annotation.VisibleForTesting;

import com.android.launcher3.icons.IconNormalizer;
import com.android.wm.shell.R;

import java.lang.annotation.Retention;
@@ -58,6 +59,8 @@ public class BubblePositioner {

    /** When the bubbles are collapsed in a stack only some of them are shown, this is how many. **/
    public static final int NUM_VISIBLE_WHEN_RESTING = 2;
    /** Indicates a bubble's height should be the maximum available space. **/
    public static final int MAX_HEIGHT = -1;

    private Context mContext;
    private WindowManager mWindowManager;
@@ -68,13 +71,16 @@ public class BubblePositioner {
    private int mMaxBubbles;

    private int mBubbleSize;
    private int mBubbleBadgeSize;
    private int mSpacingBetweenBubbles;
    private int mExpandedViewLargeScreenWidth;
    private int mExpandedViewPadding;
    private int mPointerMargin;
    private float mPointerWidth;
    private float mPointerHeight;
    private int mPointerWidth;
    private int mPointerHeight;
    private int mPointerOverlap;
    private int mManageButtonHeight;
    private int mExpandedViewMinHeight;
    private int mOverflowHeight;

    private PointF mPinLocation;
    private PointF mRestingStackPosition;
@@ -151,7 +157,6 @@ public class BubblePositioner {

        Resources res = mContext.getResources();
        mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size);
        mBubbleBadgeSize = res.getDimensionPixelSize(R.dimen.bubble_badge_size);
        mSpacingBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing);
        mDefaultMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);

@@ -161,6 +166,10 @@ public class BubblePositioner {
        mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
        mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
        mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
        mPointerOverlap = res.getDimensionPixelSize(R.dimen.bubble_pointer_overlap);
        mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_height);
        mExpandedViewMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
        mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);

        mMaxBubbles = calculateMaxBubbles();

@@ -296,8 +305,8 @@ public class BubblePositioner {
        return mPaddings;
    }

    /** Calculates the y position of the expanded view when it is expanded. */
    public float getExpandedViewY() {
    /** Gets the y position of the expanded view if it was top-aligned. */
    private float getExpandedViewYTopAligned() {
        final int top = getAvailableRect().top;
        if (showBubblesVertically()) {
            return top - mPointerWidth;
@@ -306,6 +315,116 @@ public class BubblePositioner {
        }
    }

    /** The maximum height the expanded view can be. */
    public int getMaxExpandedViewHeight(boolean isOverflow) {
        int paddingTop = showBubblesVertically()
                ? 0
                : mPointerHeight;
        int settingsHeight = isOverflow ? 0 : mManageButtonHeight;
        // Subtract pointer size because it's laid out in LinearLayout with the expanded view.
        int pointerSize = showBubblesVertically()
                ? mPointerWidth
                : (mPointerHeight + mPointerMargin);
        // Subtract top insets because availableRect.height would account for that
        int expandedContainerY = (int) getExpandedViewYTopAligned() - getInsets().top;
        return getAvailableRect().height()
                - expandedContainerY
                - paddingTop
                - settingsHeight
                - pointerSize;
    }

    /**
     * Determines the height for the bubble, ensuring a minimum height. If the height should be as
     * big as available, returns {@link #MAX_HEIGHT}.
     */
    public float getExpandedViewHeight(BubbleViewProvider bubble) {
        boolean isOverflow = bubble == null || BubbleOverflow.KEY.equals(bubble.getKey());
        float desiredHeight = isOverflow
                ? mOverflowHeight
                : ((Bubble) bubble).getDesiredHeight(mContext);
        int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight;
        desiredHeight = Math.max(manageButtonHeight + desiredHeight, mExpandedViewMinHeight);
        if (desiredHeight > getMaxExpandedViewHeight(isOverflow)) {
            return MAX_HEIGHT;
        }
        return desiredHeight;
    }

    /**
     * Gets the y position for the expanded view. This is the position on screen of the top
     * horizontal line of the expanded view.
     *
     * @param bubble the bubble being positioned.
     * @param bubblePosition the x position of the bubble if showing on top, the y position of the
     *                       bubble if showing vertically.
     * @return the y position for the expanded view.
     */
    public float getExpandedViewY(BubbleViewProvider bubble, float bubblePosition) {
        boolean isOverflow = bubble == null || BubbleOverflow.KEY.equals(bubble.getKey());
        float expandedViewHeight = getExpandedViewHeight(bubble);
        float topAlignment = getExpandedViewYTopAligned();
        if (!showBubblesVertically() || expandedViewHeight == MAX_HEIGHT) {
            // Top-align when bubbles are shown at the top or are max size.
            return topAlignment;
        }
        // If we're here, we're showing vertically & developer has made height less than maximum.
        int manageButtonHeight = isOverflow ? 0 : mManageButtonHeight;
        float pointerPosition = getPointerPosition(bubblePosition);
        float bottomIfCentered = pointerPosition + (expandedViewHeight / 2) + manageButtonHeight;
        float topIfCentered = pointerPosition - (expandedViewHeight / 2);
        if (topIfCentered > mPositionRect.top && mPositionRect.bottom > bottomIfCentered) {
            // Center it
            return pointerPosition - mPointerWidth - (expandedViewHeight / 2f);
        } else if (topIfCentered <= mPositionRect.top) {
            // Top align
            return topAlignment;
        } else {
            // Bottom align
            return mPositionRect.bottom - manageButtonHeight - expandedViewHeight - mPointerWidth;
        }
    }

    /**
     * The position the pointer points to, the center of the bubble.
     *
     * @param bubblePosition the x position of the bubble if showing on top, the y position of the
     *                       bubble if showing vertically.
     * @return the position the tip of the pointer points to. The x position if showing on top, the
     * y position if showing vertically.
     */
    public float getPointerPosition(float bubblePosition) {
        // TODO: I don't understand why it works but it does - why normalized in portrait
        //  & not in landscape? Am I missing ~2dp in the portrait expandedViewY calculation?
        final float normalizedSize = IconNormalizer.getNormalizedCircleSize(
                getBubbleSize());
        return showBubblesVertically()
                ? bubblePosition + (getBubbleSize() / 2f)
                : bubblePosition + (normalizedSize / 2f) - mPointerWidth;
    }

    /**
     * When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
     * row. When in landscape or on a large screen, they show at the left or right side in a
     * vertical row. This method accounts for screen orientation and will return an x or y value
     * for the position of the bubble in the row.
     *
     * @param index bubble index in the row.
     * @param numberOfBubbles the number of bubbles (including the overflow) in the row.
     * @return the y position of the bubble if showing vertically and the x position if showing
     * horizontally.
     */
    public float getBubbleXOrYForOrientation(int index, int numberOfBubbles) {
        final float positionInBar = index * (mBubbleSize + mSpacingBetweenBubbles);
        final float expandedStackSize = (numberOfBubbles * mBubbleSize)
                + ((numberOfBubbles - 1) * mSpacingBetweenBubbles);
        final float centerPosition = showBubblesVertically()
                ? mPositionRect.centerY()
                : mPositionRect.centerX();
        final float rowStart = centerPosition - (expandedStackSize / 2f);
        return rowStart + positionInBar;
    }

    /**
     * Sets the stack's most recent position along the edge of the screen. This is saved when the
     * last bubble is removed, so that the stack can be restored in its previous position.
+13 −7
Original line number Diff line number Diff line
@@ -874,8 +874,10 @@ public class BubbleStackView extends FrameLayout
                        mExpandedAnimationController.expandFromStack(() -> {
                            afterExpandedViewAnimation();
                        } /* after */);
                        final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
                                getBubbleIndex(mExpandedBubble));
                        mExpandedViewContainer.setTranslationX(0f);
                        mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
                        mExpandedViewContainer.setTranslationY(translationY);
                        mExpandedViewContainer.setAlpha(1f);
                    }
                    removeOnLayoutChangeListener(mOrientationChangedListener);
@@ -1524,6 +1526,7 @@ public class BubbleStackView extends FrameLayout
                    bubble.cleanupViews();
                }
                updatePointerPosition();
                updateExpandedView();
                logBubbleEvent(bubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
                return;
            }
@@ -1815,9 +1818,10 @@ public class BubbleStackView extends FrameLayout
            mTaskbarScrim.setVisibility(VISIBLE);
            mTaskbarScrim.animate().alpha(1f).start();
        }

        final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
                getBubbleIndex(mExpandedBubble));
        mExpandedViewContainer.setTranslationX(0f);
        mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
        mExpandedViewContainer.setTranslationY(translationY);
        mExpandedViewContainer.setAlpha(1f);

        int index;
@@ -1866,7 +1870,7 @@ public class BubbleStackView extends FrameLayout
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    bubbleWillBeAt + mBubbleSize / 2f,
                    mPositioner.getExpandedViewY());
                    translationY);
        }
        mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);

@@ -1970,7 +1974,7 @@ public class BubbleStackView extends FrameLayout
            mExpandedViewContainerMatrix.setScale(
                    1f, 1f,
                    expandingFromBubbleAt + mBubbleSize / 2f,
                    mPositioner.getExpandedViewY());
                    mPositioner.getExpandedViewY(mExpandedBubble, index));
        }

        mExpandedViewAlphaAnimator.reverse();
@@ -2077,7 +2081,7 @@ public class BubbleStackView extends FrameLayout
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    expandingFromBubbleDestination + mBubbleSize / 2f,
                    mPositioner.getExpandedViewY());
                    mPositioner.getExpandedViewY(mExpandedBubble, expandingFromBubbleDestination));
        }

        mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
@@ -2698,7 +2702,9 @@ public class BubbleStackView extends FrameLayout
            mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
        }
        if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
            mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY());
            mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY(mExpandedBubble,
                    mExpandedAnimationController.getBubbleXOrYForOrientation(
                            getBubbleIndex(mExpandedBubble))));
            mExpandedViewContainer.setTranslationX(0f);
            mExpandedBubble.getExpandedView().updateView(
                    mExpandedViewContainer.getLocationOnScreen());
+2 −20
Original line number Diff line number Diff line
@@ -83,12 +83,6 @@ public class ExpandedAnimationController
    private float mBubblePaddingTop;
    /** Size of each bubble. */
    private float mBubbleSizePx;
    /** Max number of bubbles shown in row above expanded view. */
    private int mBubblesMaxRendered;
    /** Max amount of space to have between bubbles when expanded. */
    private int mBubblesMaxSpace;
    /** Amount of space between the bubbles when expanded. */
    private float mSpaceBetweenBubbles;
    /** Whether the expand / collapse animation is running. */
    private boolean mAnimatingExpand = false;

@@ -211,8 +205,6 @@ public class ExpandedAnimationController
        mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
        mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
        mBubbleSizePx = mPositioner.getBubbleSize();
        mBubblesMaxRendered = mPositioner.getMaxBubbles();
        mSpaceBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing);
    }

    /**
@@ -628,14 +620,13 @@ public class ExpandedAnimationController
        }
    }

    // TODO - could move to method on bubblePositioner if mSpaceBetweenBubbles gets moved
    /**
     * When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
     * row. When in landscape or on a large screen, they show at the left or right side in a
     * vertical row. This method accounts for screen orientation and will return an x or y value
     * for the position of the bubble in the row.
     *
     * @param index Bubble index in row.
     * @param index bubble index in the row.
     * @return the y position of the bubble if showing vertically and the x position if showing
     * horizontally.
     */
@@ -643,15 +634,6 @@ public class ExpandedAnimationController
        if (mLayout == null) {
            return 0;
        }
        final float positionInBar = index * (mBubbleSizePx + mSpaceBetweenBubbles);
        Rect availableRect = mPositioner.getAvailableRect();
        final boolean isLandscape = mPositioner.showBubblesVertically();
        final float expandedStackSize = (mLayout.getChildCount() * mBubbleSizePx)
                + ((mLayout.getChildCount() - 1) * mSpaceBetweenBubbles);
        final float centerPosition = isLandscape
                ? availableRect.centerY()
                : availableRect.centerX();
        final float rowStart = centerPosition - (expandedStackSize / 2f);
        return rowStart + positionInBar;
        return mPositioner.getBubbleXOrYForOrientation(index, mLayout.getChildCount());
    }
}