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

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

Merge "New Bubbles animations!" into sc-dev

parents f3421c57 088311b4
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -398,6 +398,14 @@ public class Bubble implements BubbleViewProvider {
        }
    }

    @Override
    public void setExpandedContentAlpha(float alpha) {
        if (mExpandedView != null) {
            mExpandedView.setAlpha(alpha);
            mExpandedView.setTaskViewAlpha(alpha);
        }
    }

    /**
     * Set visibility of bubble in the expanded state.
     *
@@ -407,7 +415,7 @@ public class Bubble implements BubbleViewProvider {
     * and setting {@code false} actually means rendering the expanded view in transparent.
     */
    @Override
    public void setContentVisibility(boolean visibility) {
    public void setTaskViewVisibility(boolean visibility) {
        if (mExpandedView != null) {
            mExpandedView.setContentVisibility(visibility);
        }
+41 −2
Original line number Diff line number Diff line
@@ -85,6 +85,19 @@ public class BubbleExpandedView extends LinearLayout {
    private boolean mImeVisible;
    private boolean mNeedsNewHeight;

    /**
     * Whether we want the TaskView's content to be visible (alpha = 1f). If
     * {@link #mIsAlphaAnimating} is true, this may not reflect the TaskView's actual alpha value
     * until the animation ends.
     */
    private boolean mIsContentVisible = false;

    /**
     * Whether we're animating the TaskView's alpha value. If so, we will hold off on applying alpha
     * changes from {@link #setContentVisibility} until the animation ends.
     */
    private boolean mIsAlphaAnimating = false;

    private int mMinHeight;
    private int mOverflowHeight;
    private int mSettingsIconHeight;
@@ -464,6 +477,29 @@ public class BubbleExpandedView extends LinearLayout {
        }
    }

    /**
     * Whether we are currently animating the TaskView's alpha value. If this is set to true, calls
     * to {@link #setContentVisibility} will not be applied until this is set to false again.
     */
    void setAlphaAnimating(boolean animating) {
        mIsAlphaAnimating = animating;

        // If we're done animating, apply the correct
        if (!animating) {
            setContentVisibility(mIsContentVisible);
        }
    }

    /**
     * Sets the alpha of the underlying TaskView, since changing the expanded view's alpha does not
     * affect the TaskView since it uses a Surface.
     */
    void setTaskViewAlpha(float alpha) {
        if (mTaskView != null) {
            mTaskView.setAlpha(alpha);
        }
    }

    /**
     * Set visibility of contents in the expanded state.
     *
@@ -477,16 +513,19 @@ public class BubbleExpandedView extends LinearLayout {
            Log.d(TAG, "setContentVisibility: visibility=" + visibility
                    + " bubble=" + getBubbleKey());
        }
        mIsContentVisible = visibility;

        final float alpha = visibility ? 1f : 0f;

        mPointerView.setAlpha(alpha);
        if (mTaskView != null) {
        if (mTaskView != null && !mIsAlphaAnimating) {
            mTaskView.setAlpha(alpha);
        }
    }


    @Nullable
    View getTaskView() {
    TaskView getTaskView() {
        return mTaskView;
    }

+6 −2
Original line number Diff line number Diff line
@@ -167,8 +167,12 @@ class BubbleOverflow(
        return dotPath
    }

    override fun setContentVisibility(visible: Boolean) {
        expandedView?.setContentVisibility(visible)
    override fun setExpandedContentAlpha(alpha: Float) {
        expandedView?.alpha = alpha
    }

    override fun setTaskViewVisibility(visible: Boolean) {
        // Overflow does not have a TaskView.
    }

    override fun getIconView(): BadgedImageView? {
+176 −59
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.view.Choreographer;
@@ -123,6 +122,10 @@ public class BubbleStackView extends FrameLayout
    @VisibleForTesting
    static final int FLYOUT_HIDE_AFTER = 5000;

    private static final float EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT = 0.1f;

    private static final int EXPANDED_VIEW_ALPHA_ANIMATION_DURATION = 150;

    /**
     * How long to wait to animate the stack temporarily invisible after a drag/flyout hide
     * animation ends, if we are in fact temporarily invisible.
@@ -142,7 +145,7 @@ public class BubbleStackView extends FrameLayout

    private final PhysicsAnimator.SpringConfig mTranslateSpringConfig =
            new PhysicsAnimator.SpringConfig(
                    SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_NO_BOUNCY);
                    SpringForce.STIFFNESS_VERY_LOW, SpringForce.DAMPING_RATIO_NO_BOUNCY);

    /**
     * Handler to use for all delayed animations - this way, we can easily cancel them before
@@ -211,6 +214,9 @@ public class BubbleStackView extends FrameLayout
    /** Container for the animating-out SurfaceView. */
    private FrameLayout mAnimatingOutSurfaceContainer;

    /** Animator for animating the alpha value of the animating out SurfaceView. */
    private final ValueAnimator mAnimatingOutSurfaceAlphaAnimator = ValueAnimator.ofFloat(0f, 1f);

    /**
     * Buffer containing a screenshot of the animating-out bubble. This is drawn into the
     * SurfaceView during animations.
@@ -261,6 +267,12 @@ public class BubbleStackView extends FrameLayout
    /** Whether we're in the middle of dragging the stack around by touch. */
    private boolean mIsDraggingStack = false;

    /** Whether the expanded view has been hidden, because we are dragging out a bubble. */
    private boolean mExpandedViewHidden = false;

    /** Animator for animating the expanded view's alpha (including the TaskView inside it). */
    private final ValueAnimator mExpandedViewAlphaAnimator = ValueAnimator.ofFloat(0f, 1f);

    /**
     * The pointer index of the ACTION_DOWN event we received prior to an ACTION_UP. We'll ignore
     * touches from other pointer indices.
@@ -614,6 +626,12 @@ public class BubbleStackView extends FrameLayout
            // Show the dismiss target, if we haven't already.
            mDismissView.show();

            if (mIsExpanded && mExpandedBubble != null && v.equals(mExpandedBubble.getIconView())) {
                // Hide the expanded view if we're dragging out the expanded bubble, and we haven't
                // already hidden it.
                hideExpandedViewIfNeeded();
            }

            // First, see if the magnetized object consumes the event - if so, we shouldn't move the
            // bubble since it's stuck to the target.
            if (!passEventToMagnetizedObject(ev)) {
@@ -645,6 +663,9 @@ public class BubbleStackView extends FrameLayout
            if (!passEventToMagnetizedObject(ev)) {
                if (mBubbleData.isExpanded()) {
                    mExpandedAnimationController.snapBubbleBack(v, velX, velY);

                    // Re-show the expanded view if we hid it.
                    showExpandedViewIfNeeded();
                } else {
                    // Fling the stack to the edge, and save whether or not it's going to end up on
                    // the left side of the screen.
@@ -937,6 +958,46 @@ public class BubbleStackView extends FrameLayout
        animate()
                .setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED)
                .setDuration(FADE_IN_DURATION);

        mExpandedViewAlphaAnimator.setDuration(EXPANDED_VIEW_ALPHA_ANIMATION_DURATION);
        mExpandedViewAlphaAnimator.setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED);
        mExpandedViewAlphaAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
                    // We need to be Z ordered on top in order for alpha animations to work.
                    mExpandedBubble.getExpandedView().setSurfaceZOrderedOnTop(true);
                    mExpandedBubble.getExpandedView().setAlphaAnimating(true);
                }
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
                    mExpandedBubble.getExpandedView().setSurfaceZOrderedOnTop(false);
                    mExpandedBubble.getExpandedView().setAlphaAnimating(false);
                }
            }
        });
        mExpandedViewAlphaAnimator.addUpdateListener(valueAnimator -> {
            if (mExpandedBubble != null) {
                mExpandedBubble.setExpandedContentAlpha((float) valueAnimator.getAnimatedValue());
            }
        });

        mAnimatingOutSurfaceAlphaAnimator.setDuration(EXPANDED_VIEW_ALPHA_ANIMATION_DURATION);
        mAnimatingOutSurfaceAlphaAnimator.setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED);
        mAnimatingOutSurfaceAlphaAnimator.addUpdateListener(valueAnimator -> {
            if (!mExpandedViewHidden) {
                mAnimatingOutSurfaceView.setAlpha((float) valueAnimator.getAnimatedValue());
            }
        });
        mAnimatingOutSurfaceAlphaAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                releaseAnimatingOutBubbleBuffer();
            }
        });
    }

    /**
@@ -1539,7 +1600,8 @@ public class BubbleStackView extends FrameLayout

        // If we're expanded, screenshot the currently expanded bubble (before expanding the newly
        // selected bubble) so we can animate it out.
        if (mIsExpanded && mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
        if (mIsExpanded && mExpandedBubble != null && mExpandedBubble.getExpandedView() != null
                && !mExpandedViewHidden) {
            if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
                // Before screenshotting, have the real ActivityView show on top of other surfaces
                // so that the screenshot doesn't flicker on top of it.
@@ -1575,7 +1637,7 @@ public class BubbleStackView extends FrameLayout
            mExpandedViewContainer.setAlpha(0.0f);
            mSurfaceSynchronizer.syncSurfaceAndRun(() -> {
                if (previouslySelected != null) {
                    previouslySelected.setContentVisibility(false);
                    previouslySelected.setTaskViewVisibility(false);
                }

                updateExpandedBubble();
@@ -1656,6 +1718,58 @@ public class BubbleStackView extends FrameLayout
        requestUpdate();
    }

    /** Animate the expanded view hidden. This is done while we're dragging out a bubble. */
    private void hideExpandedViewIfNeeded() {
        if (mExpandedViewHidden
                || mExpandedBubble == null
                || mExpandedBubble.getExpandedView() == null) {
            return;
        }

        mExpandedViewHidden = true;

        // Scale down.
        PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
                .spring(AnimatableScaleMatrix.SCALE_X,
                        AnimatableScaleMatrix.getAnimatableValueForScaleFactor(
                                1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT),
                        mScaleOutSpringConfig)
                .spring(AnimatableScaleMatrix.SCALE_Y,
                        AnimatableScaleMatrix.getAnimatableValueForScaleFactor(
                                1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT),
                        mScaleOutSpringConfig)
                .addUpdateListener((target, values) ->
                        mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix))
                .start();

        // Animate alpha from 1f to 0f.
        mExpandedViewAlphaAnimator.reverse();
    }

    /**
     * Animate the expanded view visible again. This is done when we're done dragging out a bubble.
     */
    private void showExpandedViewIfNeeded() {
        if (!mExpandedViewHidden) {
            return;
        }

        mExpandedViewHidden = false;

        PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
                .spring(AnimatableScaleMatrix.SCALE_X,
                        AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
                        mScaleOutSpringConfig)
                .spring(AnimatableScaleMatrix.SCALE_Y,
                        AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
                        mScaleOutSpringConfig)
                .addUpdateListener((target, values) ->
                        mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix))
                .start();

        mExpandedViewAlphaAnimator.start();
    }

    private void animateExpansion() {
        cancelDelayedExpandCollapseSwitchAnimations();
        final boolean showVertically = mPositioner.showBubblesVertically();
@@ -1714,7 +1828,7 @@ public class BubbleStackView extends FrameLayout
        // Should not happen since we lay out before expanding, but just in case...
        if (getWidth() > 0) {
            startDelay = (long)
                    (ExpandedAnimationController.EXPAND_COLLAPSE_TARGET_ANIM_DURATION
                    (ExpandedAnimationController.EXPAND_COLLAPSE_TARGET_ANIM_DURATION * 1.2f
                            + (distanceAnimated / getWidth()) * 30);
        }

@@ -1728,20 +1842,29 @@ public class BubbleStackView extends FrameLayout
                pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
            }
            mExpandedViewContainerMatrix.setScale(
                    0f, 0f,
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    pivotX, pivotY);
        } else {
            mExpandedViewContainerMatrix.setScale(
                    0f, 0f,
                    bubbleWillBeAt + mBubbleSize / 2f, getExpandedViewY());
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    bubbleWillBeAt + mBubbleSize / 2f,
                    getExpandedViewY());
        }
        mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);

        if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
            mExpandedBubble.getExpandedView().setSurfaceZOrderedOnTop(false);
        if (mExpandedBubble.getExpandedView() != null) {
            mExpandedBubble.setExpandedContentAlpha(0f);

            // We'll be starting the alpha animation after a slight delay, so set this flag early
            // here.
            mExpandedBubble.getExpandedView().setAlphaAnimating(true);
        }

        mDelayedAnimationExecutor.executeDelayed(() -> {
            mExpandedViewAlphaAnimator.start();

            PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
            PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
                    .spring(AnimatableScaleMatrix.SCALE_X,
@@ -1796,22 +1919,15 @@ public class BubbleStackView extends FrameLayout
        // since we're about to animate collapsed.
        mExpandedAnimationController.notifyPreparingToCollapse();

        final long startDelay =
                (long) (ExpandedAnimationController.EXPAND_COLLAPSE_TARGET_ANIM_DURATION * 0.6f);
        mDelayedAnimationExecutor.executeDelayed(() -> {
        mExpandedAnimationController.collapseBackToStack(
                mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
                /* collapseTo */,
                () -> mBubbleContainer.setActiveController(mStackAnimationController));
        }, startDelay);

        if (mTaskbarScrim.getVisibility() == VISIBLE) {
            mTaskbarScrim.animate().alpha(0f).start();
        }

        // We want to visually collapse into this bubble during the animation.
        final View expandingFromBubble = mExpandedBubble.getIconView();

        int index;
        if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) {
            index = mBubbleData.getBubbles().size();
@@ -1840,31 +1956,25 @@ public class BubbleStackView extends FrameLayout
                    getExpandedViewY());
        }

        mExpandedViewAlphaAnimator.reverse();

        // When the animation completes, we should no longer be showing the content.
        if (mExpandedBubble.getExpandedView() != null) {
            mExpandedBubble.getExpandedView().setContentVisibility(false);
        }

        PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
        PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
                .spring(AnimatableScaleMatrix.SCALE_X, 0f, mScaleOutSpringConfig)
                .spring(AnimatableScaleMatrix.SCALE_Y, 0f, mScaleOutSpringConfig)
                .spring(AnimatableScaleMatrix.SCALE_X,
                        AnimatableScaleMatrix.getAnimatableValueForScaleFactor(
                                1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT),
                        mScaleOutSpringConfig)
                .spring(AnimatableScaleMatrix.SCALE_Y,
                        AnimatableScaleMatrix.getAnimatableValueForScaleFactor(
                                1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT),
                        mScaleOutSpringConfig)
                .addUpdateListener((target, values) -> {
                    if (expandingFromBubble != null) {
                        // Follow the bubble as it translates!
                        if (showVertically) {
                            mExpandedViewContainerMatrix.postTranslate(
                                    0f, expandingFromBubble.getTranslationY()
                                            - expandingFromBubbleAt);
                        } else {
                            mExpandedViewContainerMatrix.postTranslate(
                                    expandingFromBubble.getTranslationX()
                                            - expandingFromBubbleAt, 0f);
                        }
                    }

                    mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);

                    // Hide early so we don't have a tiny little expanded view still visible at the
                    // end of the scale animation.
                    if (mExpandedViewContainerMatrix.getScaleX() < 0.05f) {
                        mExpandedViewContainer.setVisibility(View.INVISIBLE);
                    }
                })
                .withEndActions(() -> {
                    final BubbleViewProvider previouslySelected = mExpandedBubble;
@@ -1882,7 +1992,7 @@ public class BubbleStackView extends FrameLayout
                    updateBadgesAndZOrder(true /* setBadgeForCollapsedStack */);
                    afterExpandedViewAnimation();
                    if (previouslySelected != null) {
                        previouslySelected.setContentVisibility(false);
                        previouslySelected.setTaskViewVisibility(false);
                    }

                    if (mPositioner.showingInTaskbar()) {
@@ -1903,22 +2013,21 @@ public class BubbleStackView extends FrameLayout
        // The surface contains a screenshot of the animating out bubble, so we just need to animate
        // it out (and then release the GraphicBuffer).
        PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer).cancel();
        PhysicsAnimator animator = PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer)
                .spring(DynamicAnimation.SCALE_X, 0f, mScaleOutSpringConfig)
                .spring(DynamicAnimation.SCALE_Y, 0f, mScaleOutSpringConfig)
                .withEndActions(this::releaseAnimatingOutBubbleBuffer);

        mAnimatingOutSurfaceAlphaAnimator.reverse();
        mExpandedViewAlphaAnimator.start();

        if (mPositioner.showBubblesVertically()) {
            float translationX = mStackAnimationController.isStackOnLeftSide()
                    ? mAnimatingOutSurfaceContainer.getTranslationX() + mBubbleSize * 2
                    : mAnimatingOutSurfaceContainer.getTranslationX();
            animator.spring(DynamicAnimation.TRANSLATION_X,
                    translationX,
                    mTranslateSpringConfig)
            PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer)
                    .spring(DynamicAnimation.TRANSLATION_X, translationX, mTranslateSpringConfig)
                    .start();
        } else {
            animator.spring(DynamicAnimation.TRANSLATION_Y,
                    mAnimatingOutSurfaceContainer.getTranslationY() - mBubbleSize * 2,
            PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer)
                    .spring(DynamicAnimation.TRANSLATION_Y,
                            mAnimatingOutSurfaceContainer.getTranslationY() - mBubbleSize,
                    mTranslateSpringConfig)
                    .start();
        }
@@ -1947,7 +2056,8 @@ public class BubbleStackView extends FrameLayout
                    pivotX, pivotY);
        } else {
            mExpandedViewContainerMatrix.setScale(
                    0f, 0f,
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
                    expandingFromBubbleDestination + mBubbleSize / 2f,
                    getExpandedViewY());
        }
@@ -1972,10 +2082,7 @@ public class BubbleStackView extends FrameLayout
                        mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
                    })
                    .withEndActions(() -> {
                        if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
                            mExpandedBubble.getExpandedView().setSurfaceZOrderedOnTop(false);
                        }

                        mExpandedViewHidden = false;
                        mIsBubbleSwitchAnimating = false;
                    })
                    .start();
@@ -2489,6 +2596,7 @@ public class BubbleStackView extends FrameLayout
                && mExpandedBubble.getExpandedView() != null) {
            BubbleExpandedView bev = mExpandedBubble.getExpandedView();
            bev.setContentVisibility(false);
            bev.setAlphaAnimating(!mIsExpansionAnimating);
            mExpandedViewContainerMatrix.setScaleX(0f);
            mExpandedViewContainerMatrix.setScaleY(0f);
            mExpandedViewContainerMatrix.setTranslate(0f, 0f);
@@ -2586,7 +2694,14 @@ public class BubbleStackView extends FrameLayout
                    mAnimatingOutBubbleBuffer.getHardwareBuffer(),
                    mAnimatingOutBubbleBuffer.getColorSpace());

            mSurfaceSynchronizer.syncSurfaceAndRun(() -> post(() -> onComplete.accept(true)));
            mAnimatingOutSurfaceView.setAlpha(1f);
            mExpandedViewContainer.setVisibility(View.GONE);

            mSurfaceSynchronizer.syncSurfaceAndRun(() -> {
                post(() -> {
                    onComplete.accept(true);
                });
            });
        });
    }

@@ -2618,7 +2733,9 @@ public class BubbleStackView extends FrameLayout
            }
        }
        mExpandedViewContainer.setPadding(leftPadding, 0, rightPadding, 0);
        if (mIsExpansionAnimating) {
            mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
        }
        if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
            mExpandedViewContainer.setTranslationY(getExpandedViewY());
            mExpandedViewContainer.setTranslationX(0f);
+10 −1
Original line number Diff line number Diff line
@@ -29,7 +29,16 @@ import androidx.annotation.Nullable;
public interface BubbleViewProvider {
    @Nullable BubbleExpandedView getExpandedView();

    void setContentVisibility(boolean visible);
    /**
     * Sets the alpha of the expanded view content. This will be applied to both the expanded view
     * container itself (the manage button, etc.) as well as the TaskView within it.
     */
    void setExpandedContentAlpha(float alpha);

    /**
     * Sets whether the contents of the bubble's TaskView should be visible.
     */
    void setTaskViewVisibility(boolean visible);

    @Nullable View getIconView();