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

Commit feb3a68d authored by Ats Jenk's avatar Ats Jenk
Browse files

Bubble bar expland/collapse animation when on left

Fix bubble bar collapse and expand animations when bubble bar is pinned
to the left.
When system language is set to an RTL language, bubble bar gets pinned
to the left edge of the screen.
Bubble bar should expand to the right and collapse to the left. Bubbles
in the bubble bar should be ordered from right to left. The most recent
bubble should be at the right in the bubble bar.

Known issue:
  - when the most recent bubble is removed, the arrow animates to a new
    position, but the background is not animated, resulting in arrow
    getting detached from the container. Will be fixed by animating the
    background.

Flag: LEGACY persist.wm.debug.bubble_bar DEVELOPMENT
Bug: 273310265
Test: with LTR language set as the system language
  - expand bubble bar with 1 bubble
  - expand bubble bar with multiple bubbles
  - select second bubble, observe after collapse it is set as first
  - dismiss a bubble from bubble bar by dragging
Test: with RTL language set as the system language
  - expand bubble bar with 1 bubble
  - expand bubble bar with multiple bubbles
  - select second bubble, observe after collapse it is set as first
  - dismiss a bubble from bubble bar by dragging

Change-Id: Ic46a5b1a6e45ad225ba509a61147cc6a8cdd0397
parent 10ac692f
Loading
Loading
Loading
Loading
+19 −9
Original line number Diff line number Diff line
@@ -50,6 +50,22 @@ class BubbleBarBackground(context: TaskbarActivityContext, private val backgroun

    var width: Float = 0f

    /**
     * Set whether the drawable is anchored to the left or right edge of the container.
     *
     * When `anchorLeft` is set to `true`, drawable left edge aligns up with the container left
     * edge. Drawable can be drawn outside container bounds on the right edge. When it is set to
     * `false` (the default), drawable right edge aligns up with the container right edge. Drawable
     * can be drawn outside container bounds on the left edge.
     */
    var anchorLeft: Boolean = false
        set(value) {
            if (field != value) {
                field = value
                invalidateSelf()
            }
        }

    init {
        paint.color = context.getColor(R.color.taskbar_background)
        paint.flags = Paint.ANTI_ALIAS_FLAG
@@ -106,15 +122,9 @@ class BubbleBarBackground(context: TaskbarActivityContext, private val backgroun

        // Draw background.
        val radius = backgroundHeight / 2f
        canvas.drawRoundRect(
            canvas.width.toFloat() - width,
            0f,
            canvas.width.toFloat(),
            canvas.height.toFloat(),
            radius,
            radius,
            paint
        )
        val left = if (anchorLeft) 0f else canvas.width.toFloat() - width
        val right = if (anchorLeft) width else canvas.width.toFloat()
        canvas.drawRoundRect(left, 0f, right, canvas.height.toFloat(), radius, radius, paint)

        if (showingArrow) {
            // Draw arrow.
+61 −18
Original line number Diff line number Diff line
@@ -197,6 +197,16 @@ public class BubbleBarView extends FrameLayout {
        updateChildrenRenderNodeProperties();
    }

    @Override
    public void onRtlPropertiesChanged(int layoutDirection) {
        // TODO(b/273310265): set this based on bubble bar position and not LTR or RTL
        mBubbleBarBackground.setAnchorLeft(layoutDirection == LAYOUT_DIRECTION_RTL);
    }

    private boolean isOnLeft() {
        return getLayoutDirection() == LAYOUT_DIRECTION_RTL;
    }

    /**
     * Updates the bounds with translation that may have been applied and returns the result.
     */
@@ -275,18 +285,31 @@ public class BubbleBarView extends FrameLayout {
        int bubbleCount = getChildCount();
        final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f;
        final boolean animate = getVisibility() == VISIBLE;
        final boolean onLeft = isOnLeft();
        for (int i = 0; i < bubbleCount; i++) {
            BubbleView bv = (BubbleView) getChildAt(i);
            bv.setTranslationY(ty);

            // the position of the bubble when the bar is fully expanded
            final float expandedX = i * (mIconSize + mIconSpacing);
            final float expandedX;
            // the position of the bubble when the bar is fully collapsed
            final float collapsedX = i == 0 ? 0 : mIconOverlapAmount;
            final float collapsedX;
            if (onLeft) {
                // If bar is on the left, bubbles are ordered right to left
                expandedX = (bubbleCount - i - 1) * (mIconSize + mIconSpacing);
                // Shift the first bubble only if there are more bubbles in addition to overflow
                collapsedX = i == 0 && bubbleCount > 2 ? mIconOverlapAmount : 0;
            } else {
                // Bubbles ordered left to right, don't move the first bubble
                expandedX = i * (mIconSize + mIconSpacing);
                collapsedX = i == 0 ? 0 : mIconOverlapAmount;
            }

            if (mIsBarExpanded) {
                // If bar is on the right, account for bubble bar expanding and shifting left
                final float expandedBarShift = onLeft ? 0 : currentWidth - expandedWidth;
                // where the bubble will end up when the animation ends
                final float targetX = currentWidth - expandedWidth + expandedX;
                final float targetX = expandedX + expandedBarShift;
                bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
                // if we're fully expanded, set the z level to 0 or to bubble elevation if dragged
                if (widthState == 1f) {
@@ -296,7 +319,9 @@ public class BubbleBarView extends FrameLayout {
                bv.setBehindStack(false, animate);
                bv.setAlpha(1);
            } else {
                final float targetX = currentWidth - collapsedWidth + collapsedX;
                // If bar is on the right, account for bubble bar expanding and shifting left
                final float collapsedBarShift = onLeft ? 0 : currentWidth - collapsedWidth;
                final float targetX = collapsedX + collapsedBarShift;
                bv.setTranslationX(widthState * (expandedX - targetX) + targetX);
                bv.setZ((MAX_BUBBLES * mBubbleElevation) - i);
                // If we're not the first bubble we're behind the stack
@@ -318,18 +343,22 @@ public class BubbleBarView extends FrameLayout {
        final float expandedArrowPosition = arrowPositionForSelectedWhenExpanded();
        final float interpolatedWidth =
                widthState * (expandedWidth - collapsedWidth) + collapsedWidth;
        final float arrowPosition;
        if (onLeft) {
            float interpolatedShift = (expandedArrowPosition - collapsedArrowPosition) * widthState;
            arrowPosition = collapsedArrowPosition + interpolatedShift;
        } else {
            if (mIsBarExpanded) {
                // when the bar is expanding, the selected bubble is always the first, so the arrow
                // always shifts with the interpolated width.
            final float arrowPosition = currentWidth - interpolatedWidth + collapsedArrowPosition;
            mBubbleBarBackground.setArrowPosition(arrowPosition);
                arrowPosition = currentWidth - interpolatedWidth + collapsedArrowPosition;
            } else {
                final float targetPosition = currentWidth - collapsedWidth + collapsedArrowPosition;
            final float arrowPosition =
                arrowPosition =
                        targetPosition + widthState * (expandedArrowPosition - targetPosition);
            mBubbleBarBackground.setArrowPosition(arrowPosition);
            }

        }
        mBubbleBarBackground.setArrowPosition(arrowPosition);
        mBubbleBarBackground.setArrowAlpha((int) (255 * widthState));
        mBubbleBarBackground.setWidth(interpolatedWidth);
    }
@@ -394,9 +423,8 @@ public class BubbleBarView extends FrameLayout {
            Log.w(TAG, "trying to update selection arrow without a selected view!");
            return;
        }
        final int index = indexOfChild(mSelectedBubbleView);
        // Find the center of the bubble when it's expanded, set the arrow position to it.
        final float tx = getPaddingStart() + index * (mIconSize + mIconSpacing) + mIconSize / 2f;
        final float tx = arrowPositionForSelectedWhenExpanded();

        if (shouldAnimate) {
            final float currentArrowPosition = mBubbleBarBackground.getArrowPositionX();
@@ -416,12 +444,27 @@ public class BubbleBarView extends FrameLayout {

    private float arrowPositionForSelectedWhenExpanded() {
        final int index = indexOfChild(mSelectedBubbleView);
        return getPaddingStart() + index * (mIconSize + mIconSpacing) + mIconSize / 2f;
        final int bubblePosition;
        if (isOnLeft()) {
            // Bubble positions are reversed. First bubble is on the right.
            bubblePosition = getChildCount() - index - 1;
        } else {
            bubblePosition = index;
        }
        return getPaddingStart() + bubblePosition * (mIconSize + mIconSpacing) + mIconSize / 2f;
    }

    private float arrowPositionForSelectedWhenCollapsed() {
        final int index = indexOfChild(mSelectedBubbleView);
        return getPaddingStart() + index * (mIconOverlapAmount) + mIconSize / 2f;
        final int bubblePosition;
        if (isOnLeft()) {
            // Bubble positions are reversed. First bubble may be shifted, if there are more
            // bubbles than the current bubble and overflow.
            bubblePosition = index == 0 && getChildCount() > 2 ? 1 : 0;
        } else {
            bubblePosition = index;
        }
        return getPaddingStart() + bubblePosition * (mIconOverlapAmount) + mIconSize / 2f;
    }

    @Override
+3 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.view.View.VISIBLE;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
@@ -289,7 +290,8 @@ public class BubbleBarViewController {
     */
    public void addBubble(BubbleBarItem b) {
        if (b != null) {
            mBarView.addView(b.getView(), 0, new FrameLayout.LayoutParams(mIconSize, mIconSize));
            mBarView.addView(b.getView(), 0,
                    new FrameLayout.LayoutParams(mIconSize, mIconSize, Gravity.LEFT));
            b.getView().setOnClickListener(mBubbleClickListener);
            mBubbleDragController.setupBubbleView(b.getView());
        } else {