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

Commit 3efcdc3c authored by Josh Tsuji's avatar Josh Tsuji Committed by Android (Google) Code Review
Browse files

Merge "Animate out bubbles in reverse of the way they animate in." into qt-r1-bubbles-dev

parents 5e706015 90ff97ee
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
@@ -664,6 +664,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.
     */
@@ -694,6 +698,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) {