diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java index 6818db6ea5..012a3620fe 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java @@ -277,6 +277,7 @@ public class BubbleBarController extends IBubblesListener.Stub { private void applyViewChanges(BubbleBarViewUpdate update) { final boolean isCollapsed = (update.expandedChanged && !update.expanded) || (!update.expandedChanged && !mBubbleBarViewController.isExpanded()); + BubbleBarItem previouslySelectedBubble = mSelectedBubble; BubbleBarBubble bubbleToSelect = null; if (!update.removedBubbles.isEmpty()) { for (int i = 0; i < update.removedBubbles.size(); i++) { @@ -321,6 +322,11 @@ public class BubbleBarController extends IBubblesListener.Stub { mBubbleBarViewController.setHiddenForBubbles(mBubbles.isEmpty()); mBubbleStashedHandleViewController.setHiddenForBubbles(mBubbles.isEmpty()); + if (mBubbles.isEmpty()) { + // all bubbles were removed. clear the selected bubble + mSelectedBubble = null; + } + if (update.updatedBubble != null) { // Updates mean the dot state may have changed; any other changes were updated in // the populateBubble step. @@ -357,6 +363,11 @@ public class BubbleBarController extends IBubblesListener.Stub { if (bubbleToSelect != null) { setSelectedBubble(bubbleToSelect); } + + if (previouslySelectedBubble == null) { + mBubbleStashController.animateToInitialState(update.expanded); + } + if (update.expandedChanged) { if (update.expanded != mBubbleBarViewController.isExpanded()) { mBubbleBarViewController.setExpandedFromSysui(update.expanded); diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java index 8e7fda8671..f5e2ddc6cf 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java @@ -206,10 +206,12 @@ public class BubbleBarViewController { // TODO: (b/273592694) animate it private void updateVisibilityForStateChange() { - if (!mHiddenForSysui && !mBubbleStashController.isStashed() && !mHiddenForNoBubbles) { + if (!mHiddenForSysui && !mHiddenForNoBubbles) { mBarView.setVisibility(VISIBLE); } else { mBarView.setVisibility(INVISIBLE); + mBarView.setAlpha(0); + mBarView.setExpanded(false); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java index 8af4ff94d8..a267211efb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java @@ -71,6 +71,7 @@ public class BubbleStashController { private int mUnstashedHeight; private boolean mBubblesShowingOnHome; private boolean mBubblesShowingOnOverview; + private boolean mIsSysuiLocked; @Nullable private AnimatorSet mAnimator; @@ -95,14 +96,6 @@ public class BubbleStashController { mStashedHeight = mHandleViewController.getStashedHeight(); mUnstashedHeight = mHandleViewController.getUnstashedHeight(); - - bubbleControllers.runAfterInit(() -> { - if (mTaskbarStashController.isStashed()) { - stashBubbleBar(); - } else { - showBubbleBar(false /* expandBubbles */); - } - }); } /** @@ -119,6 +112,40 @@ public class BubbleStashController { return mIsStashed; } + /** + * Animates the bubble bar and handle to their initial state, transitioning from the state where + * both views are invisible. Called when the first bubble is added or when the device is + * unlocked. + * + *
Normally either the bubble bar or the handle is visible, + * and {@link #showBubbleBar(boolean)} and {@link #stashBubbleBar()} are used to transition + * between these two states. But the transition from the state where both the bar and handle + * are invisible is slightly different. + * + *
The initial state will depend on the current state of the device, i.e. overview, home etc + * and whether bubbles are requested to be expanded. + */ + public void animateToInitialState(boolean expanding) { + AnimatorSet animatorSet = new AnimatorSet(); + if (expanding || mBubblesShowingOnHome || mBubblesShowingOnOverview) { + mIsStashed = false; + animatorSet.playTogether(mIconScaleForStash.animateToValue(1), + mIconTranslationYForStash.animateToValue(getBubbleBarTranslationY()), + mIconAlphaForStash.animateToValue(1)); + } else { + mIsStashed = true; + animatorSet.playTogether(mBubbleStashedHandleAlpha.animateToValue(1)); + } + + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + onIsStashedChanged(); + } + }); + animatorSet.setDuration(BAR_STASH_DURATION).start(); + } + /** * Called when launcher enters or exits the home page. Bubbles are unstashed on home. */ @@ -172,12 +199,11 @@ public class BubbleStashController { /** Called when sysui locked state changes, when locked, bubble bar is stashed. */ public void onSysuiLockedStateChange(boolean isSysuiLocked) { - if (isSysuiLocked) { - // TODO: should the normal path flip mBubblesOnHome / check if this is needed - // If we're locked, we're no longer showing on home. - mBubblesShowingOnHome = false; - mBubblesShowingOnOverview = false; - stashBubbleBar(); + if (isSysuiLocked != mIsSysuiLocked) { + mIsSysuiLocked = isSysuiLocked; + if (!mIsSysuiLocked) { + animateToInitialState(false /* expanding */); + } } } @@ -256,11 +282,7 @@ public class BubbleStashController { firstHalfDurationScale = 0.5f; secondHalfDurationScale = 0.75f; - // If we're on home, adjust the translation so the bubble bar aligns with hotseat. - // Otherwise we're either showing in an app or in overview. In either case adjust it so - // the bubble bar aligns with the taskbar. - final float translationY = mBubblesShowingOnHome ? getBubbleBarTranslationYForHotseat() - : getBubbleBarTranslationYForTaskbar(); + final float translationY = getBubbleBarTranslationY(); fullLengthAnimatorSet.playTogether( mIconScaleForStash.animateToValue(1), @@ -317,6 +339,9 @@ public class BubbleStashController { } float getBubbleBarTranslationY() { + // If we're on home, adjust the translation so the bubble bar aligns with hotseat. + // Otherwise we're either showing in an app or in overview. In either case adjust it so + // the bubble bar aligns with the taskbar. return mBubblesShowingOnHome ? getBubbleBarTranslationYForHotseat() : getBubbleBarTranslationYForTaskbar(); } diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java index 26756d4856..4c197f6b57 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java @@ -52,6 +52,7 @@ public class BubbleStashedHandleViewController { private BubbleStashController mBubbleStashController; private RegionSamplingHelper mRegionSamplingHelper; private int mBarSize; + private int mStashedTaskbarHeight; private int mStashedHandleWidth; private int mStashedHandleHeight; @@ -92,7 +93,7 @@ public class BubbleStashedHandleViewController { mTaskbarStashedHandleAlpha.get(0).setValue(0); - final int stashedTaskbarHeight = resources.getDimensionPixelSize( + mStashedTaskbarHeight = resources.getDimensionPixelSize( R.dimen.bubblebar_stashed_size); mStashedHandleView.setOutlineProvider(new ViewOutlineProvider() { @Override @@ -115,22 +116,25 @@ public class BubbleStashedHandleViewController { } }, Executors.UI_HELPER_EXECUTOR); - mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> { - // As more bubbles get added, the icon bounds become larger. To ensure a consistent - // handle bar position, we pin it to the edge of the screen. - Rect bubblebarRect = mBarViewController.getBubbleBarBounds(); - final int stashedCenterY = view.getHeight() - stashedTaskbarHeight / 2; + mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> + updateBounds()); + } - mStashedHandleBounds.set( - bubblebarRect.right - mStashedHandleWidth, - stashedCenterY - mStashedHandleHeight / 2, - bubblebarRect.right, - stashedCenterY + mStashedHandleHeight / 2); - mStashedHandleView.updateSampledRegion(mStashedHandleBounds); + private void updateBounds() { + // As more bubbles get added, the icon bounds become larger. To ensure a consistent + // handle bar position, we pin it to the edge of the screen. + Rect bubblebarRect = mBarViewController.getBubbleBarBounds(); + final int stashedCenterY = mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2; - view.setPivotX(view.getWidth()); - view.setPivotY(view.getHeight() - stashedTaskbarHeight / 2f); - }); + mStashedHandleBounds.set( + bubblebarRect.right - mStashedHandleWidth, + stashedCenterY - mStashedHandleHeight / 2, + bubblebarRect.right, + stashedCenterY + mStashedHandleHeight / 2); + mStashedHandleView.updateSampledRegion(mStashedHandleBounds); + + mStashedHandleView.setPivotX(mStashedHandleView.getWidth()); + mStashedHandleView.setPivotY(mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2f); } public void onDestroy() { @@ -188,6 +192,7 @@ public class BubbleStashedHandleViewController { mStashedHandleView.setVisibility(VISIBLE); } else { mStashedHandleView.setVisibility(INVISIBLE); + mStashedHandleView.setAlpha(0); } updateRegionSampling(); } @@ -235,6 +240,9 @@ public class BubbleStashedHandleViewController { */ public Animator createRevealAnimToIsStashed(boolean isStashed) { Rect bubbleBarBounds = new Rect(mBarViewController.getBubbleBarBounds()); + // the bubble bar may have been invisible when the bounds were previously calculated, + // update them again to ensure they're correct. + updateBounds(); // Account for the full visual height of the bubble bar int heightDiff = (mBarSize - bubbleBarBounds.height()) / 2;