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

Commit 495fe1d2 authored by Liran Binyamin's avatar Liran Binyamin Committed by Android (Google) Code Review
Browse files

Merge "Animate the bubble bar on dismiss" into main

parents 3be4c7d4 7e387fa5
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ public class BubbleBarView extends FrameLayout {

    public static final long FADE_OUT_ANIM_POSITION_DURATION_MS = 100L;
    public static final long FADE_IN_ANIM_ALPHA_DURATION_MS = 100L;
    public static final long FADE_OUT_BUBBLE_BAR_DURATION_MS = 150L;
    private static final String TAG = "BubbleBarView";
    // TODO: (b/273594744) calculate the amount of space we have and base the max on that
    //  if it's smaller than 5.
@@ -146,6 +147,9 @@ public class BubbleBarView extends FrameLayout {
    // collapsed state and 1 to the fully expanded state.
    private ValueAnimator mWidthAnimator = createExpansionAnimator(/* expanding = */ false);

    @Nullable
    private ValueAnimator mDismissAnimator = null;

    /** An animator used for animating individual bubbles in the bubble bar while expanded. */
    @Nullable
    private BubbleAnimator mBubbleAnimator = null;
@@ -798,11 +802,11 @@ public class BubbleBarView extends FrameLayout {
    /** Removes the given bubble from the bubble bar. */
    public void removeBubble(View bubble) {
        if (isExpanded()) {
            // TODO b/347062801 - animate the bubble bar if the last bubble is removed
            final boolean dismissedByDrag = mDraggedBubbleView == bubble;
            if (dismissedByDrag) {
                mDismissedByDragBubbleView = mDraggedBubbleView;
            }
            boolean removingLastRemainingBubble = getBubbleChildCount() == 1;
            int bubbleCount = getChildCount();
            mBubbleAnimator = new BubbleAnimator(mIconSize, mExpandedBarIconsSpacing,
                    bubbleCount, mBubbleBarLocation.isOnLeft(isLayoutRtl()));
@@ -840,7 +844,10 @@ public class BubbleBarView extends FrameLayout {
                            : bubbleIndex == bubbleCount - 1;
            mBubbleAnimator.animateRemovedBubble(
                    indexOfChild(bubble), indexOfChild(mSelectedBubbleView), removingLastBubble,
                    listener);
                    removingLastRemainingBubble, listener);
            if (removingLastRemainingBubble && mDismissAnimator == null) {
                createDismissAnimator().start();
            }
        } else {
            removeView(bubble);
        }
@@ -861,6 +868,28 @@ public class BubbleBarView extends FrameLayout {
        updateDotsAndBadgesIfCollapsed();
    }

    private ValueAnimator createDismissAnimator() {
        ValueAnimator animator =
                ValueAnimator.ofFloat(0, 1).setDuration(FADE_OUT_BUBBLE_BAR_DURATION_MS);
        animator.setInterpolator(Interpolators.EMPHASIZED);
        Runnable onEnd = () -> {
            mDismissAnimator = null;
            setAlpha(0);
        };
        addAnimationCallBacks(animator, /* onStart= */ null, onEnd,
                /* onUpdate= */ anim -> setAlpha(1 - anim.getAnimatedFraction()));
        mDismissAnimator = animator;
        return animator;
    }

    /** Dismisses the bubble bar */
    public void dismiss(Runnable onDismissed) {
        if (mDismissAnimator == null) {
            createDismissAnimator().start();
        }
        addAnimationCallBacks(mDismissAnimator, null, onDismissed, null);
    }

    /**
     * Return child views in the order which they are shown on the screen.
     * <p>
+9 −6
Original line number Diff line number Diff line
@@ -597,13 +597,17 @@ public class BubbleBarViewController {
    public void setHiddenForBubbles(boolean hidden) {
        if (mHiddenForNoBubbles != hidden) {
            mHiddenForNoBubbles = hidden;
            updateVisibilityForStateChange();
            if (hidden) {
                mBarView.setAlpha(0);
                mBarView.dismiss(() -> {
                    updateVisibilityForStateChange();
                    mBarView.setExpanded(false);
                    adjustTaskbarAndHotseatToBubbleBarState(/* isBubbleBarExpanded= */ false);
                    mActivity.bubbleBarVisibilityChanged(/* isVisible= */ false);
                });
            } else {
                updateVisibilityForStateChange();
                mActivity.bubbleBarVisibilityChanged(/* isVisible= */ true);
            }
            mActivity.bubbleBarVisibilityChanged(!hidden);
        }
    }

@@ -636,7 +640,6 @@ public class BubbleBarViewController {
        }
    }

    // TODO: (b/273592694) animate it
    private void updateVisibilityForStateChange() {
        if (!mHiddenForSysui && !mHiddenForNoBubbles && !mHiddenForStashed) {
            mBarView.setVisibility(VISIBLE);
+30 −18
Original line number Diff line number Diff line
@@ -49,23 +49,30 @@ class BubbleAnimator(
        bubbleIndex: Int,
        selectedBubbleIndex: Int,
        removingLastBubble: Boolean,
        listener: Listener
        removingLastRemainingBubble: Boolean,
        listener: Listener,
    ) {
        animator = createAnimator(listener)
        state = State.RemovingBubble(bubbleIndex, selectedBubbleIndex, removingLastBubble)
        state =
            State.RemovingBubble(
                bubbleIndex = bubbleIndex,
                selectedBubbleIndex = selectedBubbleIndex,
                removingLastBubble = removingLastBubble,
                removingLastRemainingBubble = removingLastRemainingBubble,
            )
        animator.start()
    }

    fun animateNewAndRemoveOld(
        selectedBubbleIndex: Int,
        removedBubbleIndex: Int,
        listener: Listener
        listener: Listener,
    ) {
        animator = createAnimator(listener)
        state =
            State.AddingAndRemoving(
                selectedBubbleIndex = selectedBubbleIndex,
                removedBubbleIndex = removedBubbleIndex
                removedBubbleIndex = removedBubbleIndex,
            )
        animator.start()
    }
@@ -111,20 +118,22 @@ class BubbleAnimator(
                getBubbleTranslationXWhileScalingBubble(
                    bubbleIndex = bubbleIndex,
                    scalingBubbleIndex = 0,
                    bubbleScale = animator.animatedFraction
                    bubbleScale = animator.animatedFraction,
                )

            is State.RemovingBubble ->
                getBubbleTranslationXWhileScalingBubble(
                    bubbleIndex = bubbleIndex,
                    scalingBubbleIndex = state.bubbleIndex,
                    bubbleScale = 1 - animator.animatedFraction
                    bubbleScale = 1 - animator.animatedFraction,
                )

            is State.AddingAndRemoving ->
                getBubbleTranslationXWhileAddingBubbleAtLimit(
                    bubbleIndex = bubbleIndex,
                    removedBubbleIndex = state.removedBubbleIndex,
                    addedBubbleScale = animator.animatedFraction,
                    removedBubbleScale = 1 - animator.animatedFraction
                    removedBubbleScale = 1 - animator.animatedFraction,
                )
        }
    }
@@ -176,10 +185,11 @@ class BubbleAnimator(
                    getBubbleTranslationXWhileScalingBubble(
                        bubbleIndex = state.selectedBubbleIndex,
                        scalingBubbleIndex = 0,
                        bubbleScale = animator.animatedFraction
                        bubbleScale = animator.animatedFraction,
                    )
                tx + iconSize / 2f
            }

            is State.RemovingBubble -> getArrowPositionWhenRemovingBubble(state)
            is State.AddingAndRemoving -> {
                // we never remove the selected bubble, so the arrow stays pointing to its center
@@ -188,22 +198,23 @@ class BubbleAnimator(
                        bubbleIndex = state.selectedBubbleIndex,
                        removedBubbleIndex = state.removedBubbleIndex,
                        addedBubbleScale = animator.animatedFraction,
                        removedBubbleScale = 1 - animator.animatedFraction
                        removedBubbleScale = 1 - animator.animatedFraction,
                    )
                tx + iconSize / 2f
            }
        }
    }

    private fun getArrowPositionWhenRemovingBubble(state: State.RemovingBubble): Float {
        return if (state.selectedBubbleIndex != state.bubbleIndex) {
            // if we're not removing the selected bubble, the selected bubble doesn't change so just
            // return the translation X of the selected bubble and add half icon
    private fun getArrowPositionWhenRemovingBubble(state: State.RemovingBubble): Float =
        if (state.selectedBubbleIndex != state.bubbleIndex || state.removingLastRemainingBubble) {
            // if we're not removing the selected bubble or if we're removing the last remaining
            // bubble, the selected bubble doesn't change so just return the translation X of the
            // selected bubble and add half icon
            val tx =
                getBubbleTranslationXWhileScalingBubble(
                    bubbleIndex = state.selectedBubbleIndex,
                    scalingBubbleIndex = state.bubbleIndex,
                    bubbleScale = 1 - animator.animatedFraction
                    bubbleScale = 1 - animator.animatedFraction,
                )
            tx + iconSize / 2f
        } else {
@@ -238,7 +249,6 @@ class BubbleAnimator(
                }
            }
        }
    }

    /**
     * Returns the translation X for the bubble at index {@code bubbleIndex} when the bubble bar is
@@ -251,7 +261,7 @@ class BubbleAnimator(
    private fun getBubbleTranslationXWhileScalingBubble(
        bubbleIndex: Int,
        scalingBubbleIndex: Int,
        bubbleScale: Float
        bubbleScale: Float,
    ): Float {
        val iconAndSpacing = iconSize + expandedBarIconSpacing
        // the bubble is scaling from the center, so we need to adjust its translation so
@@ -300,7 +310,7 @@ class BubbleAnimator(
        bubbleIndex: Int,
        removedBubbleIndex: Int,
        addedBubbleScale: Float,
        removedBubbleScale: Float
        removedBubbleScale: Float,
    ): Float {
        val iconAndSpacing = iconSize + expandedBarIconSpacing
        // the bubbles are scaling from the center, so we need to adjust their translation so
@@ -377,7 +387,9 @@ class BubbleAnimator(
            /** The index of the selected bubble. */
            val selectedBubbleIndex: Int,
            /** Whether the bubble being removed is also the last bubble. */
            val removingLastBubble: Boolean
            val removingLastBubble: Boolean,
            /** Whether we're removing the last remaining bubble. */
            val removingLastRemainingBubble: Boolean,
        ) : State

        /** A new bubble is being added and an old bubble is being removed from the bubble bar. */
+12 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.launcher3.taskbar

import android.animation.AnimatorTestRule
import android.content.ComponentName
import android.content.Intent
import android.platform.test.annotations.EnableFlags
@@ -75,7 +76,9 @@ class TaskbarOverflowTest {

    @get:Rule(order = 3) val taskbarModeRule = TaskbarModeRule(context)

    @get:Rule(order = 4) val taskbarUnitTestRule = TaskbarUnitTestRule(this, context)
    @get:Rule(order = 4) val animatorTestRule = AnimatorTestRule(this)

    @get:Rule(order = 5) val taskbarUnitTestRule = TaskbarUnitTestRule(this, context)

    @InjectController lateinit var taskbarViewController: TaskbarViewController
    @InjectController lateinit var recentAppsController: TaskbarRecentAppsController
@@ -208,7 +211,10 @@ class TaskbarOverflowTest {
        val initialNumIcons = currentNumberOfTaskbarIcons
        val initialMaxNumIconViews = addRunningAppsAndVerifyOverflowState(5)

        runOnMainSync { bubbleBarViewController.setHiddenForBubbles(true) }
        runOnMainSync {
            bubbleBarViewController.setHiddenForBubbles(true)
            animatorTestRule.advanceTimeBy(150)
        }

        val maxNumIconViews = maxNumberOfTaskbarIcons
        assertThat(maxNumIconViews).isGreaterThan(initialMaxNumIconViews)
@@ -226,7 +232,10 @@ class TaskbarOverflowTest {
        val initialNumIcons = currentNumberOfTaskbarIcons
        val initialMaxNumIconViews = addRunningAppsAndVerifyOverflowState(5)

        runOnMainSync { bubbleBarViewController.setHiddenForBubbles(true) }
        runOnMainSync {
            bubbleBarViewController.setHiddenForBubbles(true)
            animatorTestRule.advanceTimeBy(150)
        }

        val maxNumIconViews = maxNumberOfTaskbarIcons
        assertThat(maxNumIconViews).isGreaterThan(initialMaxNumIconViews)
+6 −5
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ class BubbleAnimatorTest {
                iconSize = 40f,
                expandedBarIconSpacing = 10f,
                bubbleCount = 5,
                onLeft = false
                onLeft = false,
            )
        val listener = TestBubbleAnimatorListener()
        InstrumentationRegistry.getInstrumentation().runOnMainSync {
@@ -61,7 +61,7 @@ class BubbleAnimatorTest {
                iconSize = 40f,
                expandedBarIconSpacing = 10f,
                bubbleCount = 5,
                onLeft = false
                onLeft = false,
            )
        val listener = TestBubbleAnimatorListener()
        InstrumentationRegistry.getInstrumentation().runOnMainSync {
@@ -69,7 +69,8 @@ class BubbleAnimatorTest {
                bubbleIndex = 2,
                selectedBubbleIndex = 3,
                removingLastBubble = false,
                listener
                removingLastRemainingBubble = false,
                listener,
            )
        }

@@ -87,14 +88,14 @@ class BubbleAnimatorTest {
                iconSize = 40f,
                expandedBarIconSpacing = 10f,
                bubbleCount = 5,
                onLeft = false
                onLeft = false,
            )
        val listener = TestBubbleAnimatorListener()
        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            bubbleAnimator.animateNewAndRemoveOld(
                selectedBubbleIndex = 3,
                removedBubbleIndex = 2,
                listener
                listener,
            )
        }