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

Commit 90ff97ee authored by Joshua Tsuji's avatar Joshua Tsuji
Browse files

Animate out bubbles in reverse of the way they animate in.

Also, fixes a bug where the last bubble doesn't animate out because the stack view resizes before the animation completes.

Test: atest SystemUITests
Fixes: 134514227
Change-Id: Ic36b79d96430307e58214bc968e0d4a16e7efa77
parent bbd77995
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -802,16 +802,32 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        if (mStackView == null) {
            return;
        }

        if (mStatusBarStateListener.getCurrentState() == SHADE && hasBubbles()) {
            // Bubbles only appear in unlocked shade
            mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE);
        } else if (mStackView != null) {
        } else if (!hasBubbles() && mStackView.hasTransientBubbles()) {
            // If we only have transient bubbles, then wait until they're gone.
            mStackView.runActionAfterTransientViewAnimations(() -> {
                mStackView.setVisibility(INVISIBLE);
                updateBubblesShowing();
            });
        } else {
            mStackView.setVisibility(INVISIBLE);
        }

        // Let listeners know if bubble state changed.
        updateBubblesShowing();
    }

    /**
     * Updates the status bar window controller and the state change listener with whether bubbles
     * are currently showing.
     */
    public void updateBubblesShowing() {
        boolean hadBubbles = mStatusBarWindowController.getBubblesShowing();
        boolean hasBubblesShowing = hasBubbles() && mStackView.getVisibility() == VISIBLE;
        boolean hasBubblesShowing =
                (hasBubbles() || mStackView.hasTransientBubbles())
                        && mStackView.getVisibility() == VISIBLE;
        mStatusBarWindowController.setBubblesShowing(hasBubblesShowing);
        if (mStateChangeListener != null && hadBubbles != hasBubblesShowing) {
            mStateChangeListener.onHasBubblesChanged(hasBubblesShowing);
+8 −0
Original line number Diff line number Diff line
@@ -657,6 +657,10 @@ public class BubbleStackView extends FrameLayout {
        return mIsExpanded;
    }

    void runActionAfterTransientViewAnimations(Runnable after) {
        mStackAnimationController.runActionAfterAllViewsAndTransientRemoved(after);
    }

    /**
     * The {@link BubbleView} that is expanded, null if one does not exist.
     */
@@ -687,6 +691,10 @@ public class BubbleStackView extends FrameLayout {
        }
    }

    boolean hasTransientBubbles() {
        return mBubbleContainer.getTransientViewCount() > 0;
    }

    // via BubbleData.Listener
    void addBubble(Bubble bubble) {
        if (DEBUG_BUBBLE_STACK_VIEW) {
+32 −6
Original line number Diff line number Diff line
@@ -144,6 +144,11 @@ public class StackAnimationController extends
     */
    private boolean mFirstBubbleSpringingToTouch = false;

    /**
     * Action to run after all views, including transient views, have been removed from the layout.
     */
    @Nullable private Runnable mAfterAllViewsAndTransientRemoved = null;

    /** Horizontal offset of bubbles in the stack. */
    private float mStackOffset;
    /** Diameter of the bubble icon. */
@@ -560,6 +565,14 @@ public class StackAnimationController extends
                });
    }

    /**
     * Sets an action to run after all views, including transient views, have been removed from the
     * layout.
     */
    public void runActionAfterAllViewsAndTransientRemoved(Runnable action) {
        mAfterAllViewsAndTransientRemoved = action;
    }

    /**
     * Springs the first bubble to the given final position, with the rest of the stack 'following'.
     */
@@ -647,13 +660,26 @@ public class StackAnimationController extends

    @Override
    void onChildRemoved(View child, int index, Runnable finishRemoval) {
        // Animate the removing view in the opposite direction of the stack.
        final float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
        animationForChild(child)
                .alpha(0f, finishRemoval /* after */)
                .scaleX(ANIMATE_IN_STARTING_SCALE)
                .scaleY(ANIMATE_IN_STARTING_SCALE)
                .translationX(mStackPosition.x - (-xOffset * ANIMATE_TRANSLATION_FACTOR))
                .alpha(0f,
                        finishRemoval /* after */,
                        () -> {
                            // If this was the last transient view, run the callback.
                            if (mLayout.getTransientViewCount() == 0
                                    && mAfterAllViewsAndTransientRemoved != null) {

                                // If a 'real' view was added while we were animating out, don't run
                                // the callback since all views haven't been removed.
                                if (mLayout.getChildCount() == 0) {
                                    mAfterAllViewsAndTransientRemoved.run();
                                }

                                mAfterAllViewsAndTransientRemoved = null;
                            }
                        } /* after */)
                .scaleX(0f)
                .scaleY(0f)
                .withStiffness(ANIMATE_IN_STIFFNESS)
                .start();

        if (mLayout.getChildCount() > 0) {