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

Commit 2ad0edfc authored by Mady Mellor's avatar Mady Mellor
Browse files

Fix the overflow button disappearing suddenly during animations

A couple of things going on with this:

1) The overflow visibility was being updated when the expanded view
   animation was finished NOT when the bubble view animation was
   finished, so it would switch to be invisible before it reached
   its final spot.
2) The overflow was being animated to the resting position of
   normal bubble, when really because it disappears we should
   animate it to a spot that wouldn't be visible -- so remove the
   offset applied to its animation. When this is done, it kinda
   bounces behind the top bubble which looks a bit weird so I also
   reduced the bounciness of it.
3) If the overflow is showing the update dot, this also needs to
   be animated in / out so that it doesn't just show / hide.

Test: manual / visual - expand and collapse bubbles it and observe
                        that the overflow originates / returns to the
                        stack rather than suddenly disappearing
                      - check if you only have 1 bubble that the
                        overflow doesn't bounce past the first bubble
                        when collapsing.
Bug: 301270929

Change-Id: I175482388edbb43d0903d0dd420d24ec0e4cb7ea
parent 4fdea46e
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -318,7 +318,7 @@ public class BadgedImageView extends ConstraintLayout {
    /**
    /**
     * Animates the dot to the given scale, running the optional callback when the animation ends.
     * Animates the dot to the given scale, running the optional callback when the animation ends.
     */
     */
    private void animateDotScale(float toScale, @Nullable Runnable after) {
    public void animateDotScale(float toScale, @Nullable Runnable after) {
        mDotIsAnimating = true;
        mDotIsAnimating = true;


        // Don't restart the animation if we're already animating to the given value.
        // Don't restart the animation if we're already animating to the given value.
+4 −1
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable
import android.graphics.drawable.InsetDrawable
import android.util.PathParser
import android.util.PathParser
import android.view.LayoutInflater
import android.view.LayoutInflater
import android.view.View.VISIBLE
import android.widget.FrameLayout
import android.widget.FrameLayout
import com.android.launcher3.icons.BubbleIconFactory
import com.android.launcher3.icons.BubbleIconFactory
import com.android.wm.shell.R
import com.android.wm.shell.R
@@ -156,8 +157,10 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl


    fun setShowDot(show: Boolean) {
    fun setShowDot(show: Boolean) {
        showDot = show
        showDot = show
        if (overflowBtn?.visibility == VISIBLE) {
            overflowBtn?.updateDotVisibility(true /* animate */)
            overflowBtn?.updateDotVisibility(true /* animate */)
        }
        }
    }


    /** Creates the expanded view for bubbles showing in the stack view. */
    /** Creates the expanded view for bubbles showing in the stack view. */
    private fun createExpandedView(): BubbleExpandedView {
    private fun createExpandedView(): BubbleExpandedView {
+14 −2
Original line number Original line Diff line number Diff line
@@ -1864,6 +1864,14 @@ public class BubbleStackView extends FrameLayout
                : GONE);
                : GONE);
    }
    }


    private void updateOverflowDotVisibility(boolean expanding) {
        if (mBubbleOverflow.showDot()) {
            mBubbleOverflow.getIconView().animateDotScale(expanding ? 1 : 0f, () -> {
                mBubbleOverflow.setVisible(expanding ? VISIBLE : GONE);
            });
        }
    }

    // via BubbleData.Listener
    // via BubbleData.Listener
    void updateBubble(Bubble bubble) {
    void updateBubble(Bubble bubble) {
        animateInFlyoutForBubble(bubble);
        animateInFlyoutForBubble(bubble);
@@ -2274,6 +2282,7 @@ public class BubbleStackView extends FrameLayout
            if (mIsExpanded && mExpandedBubble.getExpandedView() != null) {
            if (mIsExpanded && mExpandedBubble.getExpandedView() != null) {
                maybeShowManageEdu();
                maybeShowManageEdu();
            }
            }
            updateOverflowDotVisibility(true /* expanding */);
        } /* after */);
        } /* after */);
        int index;
        int index;
        if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) {
        if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) {
@@ -2405,11 +2414,15 @@ public class BubbleStackView extends FrameLayout
        // since we're about to animate collapsed.
        // since we're about to animate collapsed.
        mExpandedAnimationController.notifyPreparingToCollapse();
        mExpandedAnimationController.notifyPreparingToCollapse();


        updateOverflowDotVisibility(false /* expanding */);
        final Runnable collapseBackToStack = () -> mExpandedAnimationController.collapseBackToStack(
        final Runnable collapseBackToStack = () -> mExpandedAnimationController.collapseBackToStack(
                mStackAnimationController
                mStackAnimationController
                        .getStackPositionAlongNearestHorizontalEdge()
                        .getStackPositionAlongNearestHorizontalEdge()
                /* collapseTo */,
                /* collapseTo */,
                () -> mBubbleContainer.setActiveController(mStackAnimationController));
                () -> {
                    mBubbleContainer.setActiveController(mStackAnimationController);
                    updateOverflowVisibility();
                });


        final Runnable after = () -> {
        final Runnable after = () -> {
            final BubbleViewProvider previouslySelected = mExpandedBubble;
            final BubbleViewProvider previouslySelected = mExpandedBubble;
@@ -2424,7 +2437,6 @@ public class BubbleStackView extends FrameLayout
                Log.d(TAG, BubbleDebugConfig.formatBubblesString(getBubblesOnScreen(),
                Log.d(TAG, BubbleDebugConfig.formatBubblesString(getBubblesOnScreen(),
                        mExpandedBubble));
                        mExpandedBubble));
            }
            }
            updateOverflowVisibility();
            updateZOrder();
            updateZOrder();
            updateBadges(true /* setBadgeForCollapsedStack */);
            updateBadges(true /* setBadgeForCollapsedStack */);
            afterExpandedViewAnimation();
            afterExpandedViewAnimation();
+20 −3
Original line number Original line Diff line number Diff line
@@ -34,6 +34,8 @@ import androidx.dynamicanimation.animation.SpringForce;
import com.android.wm.shell.R;
import com.android.wm.shell.R;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.bubbles.BadgedImageView;
import com.android.wm.shell.bubbles.BubbleOverflow;
import com.android.wm.shell.bubbles.BubblePositioner;
import com.android.wm.shell.bubbles.BubblePositioner;
import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
@@ -63,6 +65,12 @@ public class ExpandedAnimationController
    /** Damping ratio for expand/collapse spring. */
    /** Damping ratio for expand/collapse spring. */
    private static final float DAMPING_RATIO_MEDIUM_LOW_BOUNCY = 0.65f;
    private static final float DAMPING_RATIO_MEDIUM_LOW_BOUNCY = 0.65f;


    /**
     * Damping ratio for the overflow bubble spring; this is less bouncy so it doesn't bounce behind
     * the top bubble when it goes to disappear.
     */
    private static final float DAMPING_RATIO_OVERFLOW_BOUNCY = 0.90f;

    /** Stiffness for the expand/collapse path-following animation. */
    /** Stiffness for the expand/collapse path-following animation. */
    private static final int EXPAND_COLLAPSE_ANIM_STIFFNESS = 400;
    private static final int EXPAND_COLLAPSE_ANIM_STIFFNESS = 400;


@@ -274,9 +282,14 @@ public class ExpandedAnimationController
                // of the screen where the bubble will be stacked.
                // of the screen where the bubble will be stacked.
                path.lineTo(stackedX, p.y);
                path.lineTo(stackedX, p.y);


                // The overflow should animate to the collapse point, so 0 offset.
                final boolean isOverflow = bubble instanceof BadgedImageView
                        && BubbleOverflow.KEY.equals(((BadgedImageView) bubble).getKey());
                final float offsetY = isOverflow
                        ? 0
                        : Math.min(index, NUM_VISIBLE_WHEN_RESTING - 1) * mStackOffsetPx;
                // 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 + offsetY);
                        + Math.min(index, NUM_VISIBLE_WHEN_RESTING - 1) * mStackOffsetPx);
            }
            }


            // The lead bubble should be the bubble with the longest distance to travel when we're
            // The lead bubble should be the bubble with the longest distance to travel when we're
@@ -505,8 +518,12 @@ public class ExpandedAnimationController


    @Override
    @Override
    SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
    SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
        boolean isOverflow = (view instanceof BadgedImageView)
                && BubbleOverflow.KEY.equals(((BadgedImageView) view).getKey());
        return new SpringForce()
        return new SpringForce()
                .setDampingRatio(DAMPING_RATIO_MEDIUM_LOW_BOUNCY)
                .setDampingRatio(isOverflow
                        ? DAMPING_RATIO_OVERFLOW_BOUNCY
                        : DAMPING_RATIO_MEDIUM_LOW_BOUNCY)
                .setStiffness(SpringForce.STIFFNESS_LOW);
                .setStiffness(SpringForce.STIFFNESS_LOW);
    }
    }