From 60240207bb78ce87f6171c97aaf15402e1a71bbe Mon Sep 17 00:00:00 2001 From: Liran Binyamin Date: Mon, 17 Jul 2023 16:07:14 -0400 Subject: [PATCH] Handle the event of first bubble added. When the first bubble is added we set the visibility of the bubble bar to VISIBLE if the stash controller is unstashed. The issue is that once bubbles are gone we no longer update the stash state in the controller, so it becomes stale and can't be used when the first bubble is added. This change introduces a new method for handling the transition from the state where both bar and handle are invisible into the state where one of them becomes visible. We can't use the existing stashBubbleBar and showBubbleBar methods because those transition from one to the other. Using them when both are invisible results in one of them becoming visible and then invisible again. Fixes: 290992144 Fixes: 291074646 Test: Manual: - Add bubble in the test app by double-tapping on a chat (non expanding notification) - Observe that the handle becomes visible and the bar is invisible - Dismiss bubble - Add bubble in the test app by tapping on the button on the right (auto expanding) - Observe that the bar becomes visible and expanded Change-Id: I61334c67c255a6ed074fa8c834f4a5a1547539bf --- .../taskbar/bubbles/BubbleBarController.java | 11 ++++ .../bubbles/BubbleBarViewController.java | 4 +- .../bubbles/BubbleStashController.java | 63 +++++++++++++------ .../BubbleStashedHandleViewController.java | 38 ++++++----- 4 files changed, 81 insertions(+), 35 deletions(-) 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;