diff options
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java | 155 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java | 54 |
2 files changed, 103 insertions, 106 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index b68b7627fe8c..31cf853dce04 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -169,7 +169,7 @@ public class BubbleStackView extends FrameLayout { * Callback to run after the flyout hides. Also called if a new flyout is shown before the * previous one animates out. */ - private Runnable mAfterFlyoutHides; + private Runnable mFlyoutOnHide; /** Layout change listener that moves the stack to the nearest valid position on rotation. */ private OnLayoutChangeListener mOrientationChangedListener; @@ -1401,111 +1401,106 @@ public class BubbleStackView extends FrameLayout { @VisibleForTesting void animateInFlyoutForBubble(Bubble bubble) { final CharSequence updateMessage = bubble.getUpdateMessage(getContext()); - if (!bubble.showFlyoutForBubble()) { // In case flyout was suppressed for this update, reset now. bubble.setSuppressFlyout(false); return; } - if (updateMessage == null || isExpanded() || mIsExpansionAnimating || mIsGestureInProgress - || mBubbleToExpandAfterFlyoutCollapse != null) { + || mBubbleToExpandAfterFlyoutCollapse != null + || bubble.getIconView() == null) { // Skip the message if none exists, we're expanded or animating expansion, or we're - // about to expand a bubble from the previous tapped flyout. + // about to expand a bubble from the previous tapped flyout, or if bubble view is null. return; } - - if (bubble.getIconView() != null) { - // Temporarily suppress the dot while the flyout is visible. - bubble.getIconView().setSuppressDot( - true /* suppressDot */, false /* animate */); - - mFlyout.removeCallbacks(mAnimateInFlyout); - mFlyoutDragDeltaX = 0f; - - if (mAfterFlyoutHides != null) { - mAfterFlyoutHides.run(); + mFlyoutDragDeltaX = 0f; + clearFlyoutOnHide(); + mFlyoutOnHide = () -> { + resetDot(bubble); + if (mBubbleToExpandAfterFlyoutCollapse == null) { + return; } - - mAfterFlyoutHides = () -> { - final boolean suppressDot = !bubble.showBubbleDot(); - // If we're going to suppress the dot, make it visible first so it'll - // visibly animate away. - if (suppressDot) { - bubble.getIconView().setSuppressDot( - false /* suppressDot */, false /* animate */); - } - // Reset dot suppression. If we're not suppressing due to DND, then - // stop suppressing it with no animation (since the flyout has - // transformed into the dot). If we are suppressing due to DND, animate - // it away. - bubble.getIconView().setSuppressDot( - suppressDot /* suppressDot */, - suppressDot /* animate */); - - if (mBubbleToExpandAfterFlyoutCollapse != null) { - mBubbleData.setSelectedBubble(mBubbleToExpandAfterFlyoutCollapse); - mBubbleData.setExpanded(true); - mBubbleToExpandAfterFlyoutCollapse = null; - } - }; - - mFlyout.setVisibility(INVISIBLE); - - // Post in case layout isn't complete and getWidth returns 0. - post(() -> { - // An auto-expanding bubble could have been posted during the time it takes to - // layout. - if (isExpanded()) { - return; - } - - final Runnable afterShow = () -> { - mAnimateInFlyout = () -> { - mFlyout.setVisibility(VISIBLE); - bubble.getIconView().setSuppressDot( - true /* suppressDot */, false /* animate */); - mFlyoutDragDeltaX = - mStackAnimationController.isStackOnLeftSide() - ? -mFlyout.getWidth() - : mFlyout.getWidth(); - animateFlyoutCollapsed(false /* collapsed */, 0 /* velX */); - mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); - }; - - mFlyout.postDelayed(mAnimateInFlyout, 200); + mBubbleData.setSelectedBubble(mBubbleToExpandAfterFlyoutCollapse); + mBubbleData.setExpanded(true); + mBubbleToExpandAfterFlyoutCollapse = null; + }; + mFlyout.setVisibility(INVISIBLE); + + // Temporarily suppress the dot while the flyout is visible. + bubble.getIconView().setSuppressDot( + true /* suppressDot */, false /* animate */); + + // Start flyout expansion. Post in case layout isn't complete and getWidth returns 0. + post(() -> { + // An auto-expanding bubble could have been posted during the time it takes to + // layout. + if (isExpanded()) { + return; + } + final Runnable expandFlyoutAfterDelay = () -> { + mAnimateInFlyout = () -> { + mFlyout.setVisibility(VISIBLE); + mFlyoutDragDeltaX = + mStackAnimationController.isStackOnLeftSide() + ? -mFlyout.getWidth() + : mFlyout.getWidth(); + animateFlyoutCollapsed(false /* collapsed */, 0 /* velX */); + mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); }; - - mFlyout.setupFlyoutStartingAsDot( - updateMessage, mStackAnimationController.getStackPosition(), getWidth(), - mStackAnimationController.isStackOnLeftSide(), - bubble.getIconView().getBadgeColor(), - afterShow, - mAfterFlyoutHides, - bubble.getIconView().getDotCenter()); - mFlyout.bringToFront(); - }); - } - + mFlyout.postDelayed(mAnimateInFlyout, 200); + }; + mFlyout.setupFlyoutStartingAsDot( + updateMessage, mStackAnimationController.getStackPosition(), getWidth(), + mStackAnimationController.isStackOnLeftSide(), + bubble.getIconView().getBadgeColor() /* dotColor */, + expandFlyoutAfterDelay /* onLayoutComplete */, + mFlyoutOnHide, + bubble.getIconView().getDotCenter()); + mFlyout.bringToFront(); + }); mFlyout.removeCallbacks(mHideFlyout); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__FLYOUT); } - /** Hide the flyout immediately and cancel any pending hide runnables. */ - private void hideFlyoutImmediate() { - if (mAfterFlyoutHides != null) { - mAfterFlyoutHides.run(); + private void resetDot(Bubble bubble) { + final boolean suppressDot = !bubble.showBubbleDot(); + // If we're going to suppress the dot, make it visible first so it'll + // visibly animate away. + + if (suppressDot) { + bubble.getIconView().setSuppressDot( + false /* suppressDot */, false /* animate */); } + // Reset dot suppression. If we're not suppressing due to DND, then + // stop suppressing it with no animation (since the flyout has + // transformed into the dot). If we are suppressing due to DND, animate + // it away. + bubble.getIconView().setSuppressDot( + suppressDot /* suppressDot */, + suppressDot /* animate */); + } + /** Hide the flyout immediately and cancel any pending hide runnables. */ + private void hideFlyoutImmediate() { + clearFlyoutOnHide(); mFlyout.removeCallbacks(mAnimateInFlyout); mFlyout.removeCallbacks(mHideFlyout); mFlyout.hideFlyout(); } + private void clearFlyoutOnHide() { + mFlyout.removeCallbacks(mAnimateInFlyout); + if (mFlyoutOnHide == null) { + return; + } + mFlyoutOnHide.run(); + mFlyoutOnHide = null; + } + @Override public void getBoundsOnScreen(Rect outRect) { if (!mIsExpanded) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java index 603c4169c169..4512aa822e3b 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java @@ -61,7 +61,7 @@ public class BubbleView extends FrameLayout { // mBubbleIconFactory cannot be static because it depends on Context. private BubbleIconFactory mBubbleIconFactory; - private boolean mSuppressDot = false; + private boolean mSuppressDot; private Bubble mBubble; @@ -140,6 +140,7 @@ public class BubbleView extends FrameLayout { public void setAppIcon(Drawable appIcon) { mUserBadgedAppIcon = appIcon; } + /** * @return the {@link ExpandableNotificationRow} view to display notification content when the * bubble is expanded. @@ -154,7 +155,6 @@ public class BubbleView extends FrameLayout { updateDotVisibility(animate, null /* after */); } - /** * Sets whether or not to hide the dot even if we'd otherwise show it. This is used while the * flyout is visible or animating, to hide the dot until the flyout visually transforms into it. @@ -166,7 +166,7 @@ public class BubbleView extends FrameLayout { /** Sets the position of the 'new' dot, animating it out and back in if requested. */ void setDotPosition(boolean onLeft, boolean animate) { - if (animate && onLeft != mBadgedImageView.getDotOnLeft() && !mSuppressDot) { + if (animate && onLeft != mBadgedImageView.getDotOnLeft() && shouldShowDot()) { animateDot(false /* showDot */, () -> { mBadgedImageView.setDotOnLeft(onLeft); animateDot(true /* showDot */, null); @@ -190,12 +190,12 @@ public class BubbleView extends FrameLayout { * after animation if requested. */ private void updateDotVisibility(boolean animate, Runnable after) { - boolean showDot = mBubble.showBubbleDot() && !mSuppressDot; - + final boolean showDot = shouldShowDot(); if (animate) { animateDot(showDot, after); } else { mBadgedImageView.setShowDot(showDot); + mBadgedImageView.setDotScale(showDot ? 1f : 0f); } } @@ -203,27 +203,25 @@ public class BubbleView extends FrameLayout { * Animates the badge to show or hide. */ private void animateDot(boolean showDot, Runnable after) { - if (mBadgedImageView.isShowingDot() != showDot) { - if (showDot) { - mBadgedImageView.setShowDot(true); - } - mBadgedImageView.clearAnimation(); - mBadgedImageView.animate().setDuration(200) - .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) - .setUpdateListener((valueAnimator) -> { - float fraction = valueAnimator.getAnimatedFraction(); - fraction = showDot ? fraction : 1f - fraction; - mBadgedImageView.setDotScale(fraction); - }).withEndAction(() -> { - if (!showDot) { - mBadgedImageView.setShowDot(false); - } - - if (after != null) { - after.run(); - } - }).start(); + if (mBadgedImageView.isShowingDot() == showDot) { + return; } + // Do NOT wait until after animation ends to setShowDot + // to avoid overriding more recent showDot states. + mBadgedImageView.setShowDot(showDot); + mBadgedImageView.clearAnimation(); + mBadgedImageView.animate().setDuration(200) + .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) + .setUpdateListener((valueAnimator) -> { + float fraction = valueAnimator.getAnimatedFraction(); + fraction = showDot ? fraction : 1f - fraction; + mBadgedImageView.setDotScale(fraction); + }).withEndAction(() -> { + mBadgedImageView.setDotScale(showDot ? 1f : 0f); + if (after != null) { + after.run(); + } + }).start(); } void updateViews() { @@ -273,7 +271,11 @@ public class BubbleView extends FrameLayout { iconPath.transform(matrix); mBadgedImageView.drawDot(iconPath); - animateDot(mBubble.showBubbleDot() /* showDot */, null /* after */); + animateDot(shouldShowDot(), null /* after */); + } + + boolean shouldShowDot() { + return mBubble.showBubbleDot() && !mSuppressDot; } int getBadgeColor() { |