Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +75 −80 Original line number Original line Diff line number Diff line Loading @@ -168,7 +168,7 @@ public class BubbleStackView extends FrameLayout { * Callback to run after the flyout hides. Also called if a new flyout is shown before the * Callback to run after the flyout hides. Also called if a new flyout is shown before the * previous one animates out. * previous one animates out. */ */ private Runnable mAfterFlyoutHides; private Runnable mFlyoutOnHide; /** Layout change listener that moves the stack to the nearest valid position on rotation. */ /** Layout change listener that moves the stack to the nearest valid position on rotation. */ private OnLayoutChangeListener mOrientationChangedListener; private OnLayoutChangeListener mOrientationChangedListener; Loading Loading @@ -1366,73 +1366,48 @@ public class BubbleStackView extends FrameLayout { @VisibleForTesting @VisibleForTesting void animateInFlyoutForBubble(Bubble bubble) { void animateInFlyoutForBubble(Bubble bubble) { final CharSequence updateMessage = bubble.getUpdateMessage(getContext()); final CharSequence updateMessage = bubble.getUpdateMessage(getContext()); if (!bubble.showFlyoutForBubble()) { if (!bubble.showFlyoutForBubble()) { // In case flyout was suppressed for this update, reset now. // In case flyout was suppressed for this update, reset now. bubble.setSuppressFlyout(false); bubble.setSuppressFlyout(false); return; return; } } if (updateMessage == null if (updateMessage == null || isExpanded() || isExpanded() || mIsExpansionAnimating || mIsExpansionAnimating || mIsGestureInProgress || mIsGestureInProgress || mBubbleToExpandAfterFlyoutCollapse != null) { || mBubbleToExpandAfterFlyoutCollapse != null || bubble.getIconView() == null) { // Skip the message if none exists, we're expanded or animating expansion, or we're // 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; 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; mFlyoutDragDeltaX = 0f; clearFlyoutOnHide(); if (mAfterFlyoutHides != null) { mFlyoutOnHide = () -> { mAfterFlyoutHides.run(); 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.setSelectedBubble(mBubbleToExpandAfterFlyoutCollapse); mBubbleData.setExpanded(true); mBubbleData.setExpanded(true); mBubbleToExpandAfterFlyoutCollapse = null; mBubbleToExpandAfterFlyoutCollapse = null; } }; }; mFlyout.setVisibility(INVISIBLE); mFlyout.setVisibility(INVISIBLE); // Post in case layout isn't complete and getWidth returns 0. // 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(() -> { post(() -> { // An auto-expanding bubble could have been posted during the time it takes to // An auto-expanding bubble could have been posted during the time it takes to // layout. // layout. if (isExpanded()) { if (isExpanded()) { return; return; } } final Runnable expandFlyoutAfterDelay = () -> { final Runnable afterShow = () -> { mAnimateInFlyout = () -> { mAnimateInFlyout = () -> { mFlyout.setVisibility(VISIBLE); mFlyout.setVisibility(VISIBLE); bubble.getIconView().setSuppressDot( true /* suppressDot */, false /* animate */); mFlyoutDragDeltaX = mFlyoutDragDeltaX = mStackAnimationController.isStackOnLeftSide() mStackAnimationController.isStackOnLeftSide() ? -mFlyout.getWidth() ? -mFlyout.getWidth() Loading @@ -1440,37 +1415,57 @@ public class BubbleStackView extends FrameLayout { animateFlyoutCollapsed(false /* collapsed */, 0 /* velX */); animateFlyoutCollapsed(false /* collapsed */, 0 /* velX */); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); }; }; mFlyout.postDelayed(mAnimateInFlyout, 200); mFlyout.postDelayed(mAnimateInFlyout, 200); }; }; mFlyout.setupFlyoutStartingAsDot( mFlyout.setupFlyoutStartingAsDot( updateMessage, mStackAnimationController.getStackPosition(), getWidth(), updateMessage, mStackAnimationController.getStackPosition(), getWidth(), mStackAnimationController.isStackOnLeftSide(), mStackAnimationController.isStackOnLeftSide(), bubble.getIconView().getBadgeColor(), bubble.getIconView().getBadgeColor() /* dotColor */, afterShow, expandFlyoutAfterDelay /* onLayoutComplete */, mAfterFlyoutHides, mFlyoutOnHide, bubble.getIconView().getDotCenter()); bubble.getIconView().getDotCenter()); mFlyout.bringToFront(); mFlyout.bringToFront(); }); }); } mFlyout.removeCallbacks(mHideFlyout); mFlyout.removeCallbacks(mHideFlyout); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__FLYOUT); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__FLYOUT); } } /** Hide the flyout immediately and cancel any pending hide runnables. */ private void resetDot(Bubble bubble) { private void hideFlyoutImmediate() { final boolean suppressDot = !bubble.showBubbleDot(); if (mAfterFlyoutHides != null) { // If we're going to suppress the dot, make it visible first so it'll mAfterFlyoutHides.run(); // 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(mAnimateInFlyout); mFlyout.removeCallbacks(mHideFlyout); mFlyout.removeCallbacks(mHideFlyout); mFlyout.hideFlyout(); mFlyout.hideFlyout(); } } private void clearFlyoutOnHide() { mFlyout.removeCallbacks(mAnimateInFlyout); if (mFlyoutOnHide == null) { return; } mFlyoutOnHide.run(); mFlyoutOnHide = null; } @Override @Override public void getBoundsOnScreen(Rect outRect) { public void getBoundsOnScreen(Rect outRect) { if (!mIsExpanded) { if (!mIsExpanded) { Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java +28 −26 Original line number Original line Diff line number Diff line Loading @@ -61,7 +61,7 @@ public class BubbleView extends FrameLayout { // mBubbleIconFactory cannot be static because it depends on Context. // mBubbleIconFactory cannot be static because it depends on Context. private BubbleIconFactory mBubbleIconFactory; private BubbleIconFactory mBubbleIconFactory; private boolean mSuppressDot = false; private boolean mSuppressDot; private Bubble mBubble; private Bubble mBubble; Loading Loading @@ -140,6 +140,7 @@ public class BubbleView extends FrameLayout { public void setAppIcon(Drawable appIcon) { public void setAppIcon(Drawable appIcon) { mUserBadgedAppIcon = appIcon; mUserBadgedAppIcon = appIcon; } } /** /** * @return the {@link ExpandableNotificationRow} view to display notification content when the * @return the {@link ExpandableNotificationRow} view to display notification content when the * bubble is expanded. * bubble is expanded. Loading @@ -154,7 +155,6 @@ public class BubbleView extends FrameLayout { updateDotVisibility(animate, null /* after */); updateDotVisibility(animate, null /* after */); } } /** /** * Sets whether or not to hide the dot even if we'd otherwise show it. This is used while the * 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. * flyout is visible or animating, to hide the dot until the flyout visually transforms into it. Loading @@ -166,7 +166,7 @@ public class BubbleView extends FrameLayout { /** Sets the position of the 'new' dot, animating it out and back in if requested. */ /** Sets the position of the 'new' dot, animating it out and back in if requested. */ void setDotPosition(boolean onLeft, boolean animate) { void setDotPosition(boolean onLeft, boolean animate) { if (animate && onLeft != mBadgedImageView.getDotOnLeft() && !mSuppressDot) { if (animate && onLeft != mBadgedImageView.getDotOnLeft() && shouldShowDot()) { animateDot(false /* showDot */, () -> { animateDot(false /* showDot */, () -> { mBadgedImageView.setDotOnLeft(onLeft); mBadgedImageView.setDotOnLeft(onLeft); animateDot(true /* showDot */, null); animateDot(true /* showDot */, null); Loading @@ -190,12 +190,12 @@ public class BubbleView extends FrameLayout { * after animation if requested. * after animation if requested. */ */ private void updateDotVisibility(boolean animate, Runnable after) { private void updateDotVisibility(boolean animate, Runnable after) { boolean showDot = mBubble.showBubbleDot() && !mSuppressDot; final boolean showDot = shouldShowDot(); if (animate) { if (animate) { animateDot(showDot, after); animateDot(showDot, after); } else { } else { mBadgedImageView.setShowDot(showDot); mBadgedImageView.setShowDot(showDot); mBadgedImageView.setDotScale(showDot ? 1f : 0f); } } } } Loading @@ -203,10 +203,12 @@ public class BubbleView extends FrameLayout { * Animates the badge to show or hide. * Animates the badge to show or hide. */ */ private void animateDot(boolean showDot, Runnable after) { private void animateDot(boolean showDot, Runnable after) { if (mBadgedImageView.isShowingDot() != showDot) { if (mBadgedImageView.isShowingDot() == showDot) { if (showDot) { return; mBadgedImageView.setShowDot(true); } } // Do NOT wait until after animation ends to setShowDot // to avoid overriding more recent showDot states. mBadgedImageView.setShowDot(showDot); mBadgedImageView.clearAnimation(); mBadgedImageView.clearAnimation(); mBadgedImageView.animate().setDuration(200) mBadgedImageView.animate().setDuration(200) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) Loading @@ -215,16 +217,12 @@ public class BubbleView extends FrameLayout { fraction = showDot ? fraction : 1f - fraction; fraction = showDot ? fraction : 1f - fraction; mBadgedImageView.setDotScale(fraction); mBadgedImageView.setDotScale(fraction); }).withEndAction(() -> { }).withEndAction(() -> { if (!showDot) { mBadgedImageView.setDotScale(showDot ? 1f : 0f); mBadgedImageView.setShowDot(false); } if (after != null) { if (after != null) { after.run(); after.run(); } } }).start(); }).start(); } } } void updateViews() { void updateViews() { if (mBubble == null || mBubbleIconFactory == null) { if (mBubble == null || mBubbleIconFactory == null) { Loading Loading @@ -273,7 +271,11 @@ public class BubbleView extends FrameLayout { iconPath.transform(matrix); iconPath.transform(matrix); mBadgedImageView.drawDot(iconPath); mBadgedImageView.drawDot(iconPath); animateDot(mBubble.showBubbleDot() /* showDot */, null /* after */); animateDot(shouldShowDot(), null /* after */); } boolean shouldShowDot() { return mBubble.showBubbleDot() && !mSuppressDot; } } int getBadgeColor() { int getBadgeColor() { Loading Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +75 −80 Original line number Original line Diff line number Diff line Loading @@ -168,7 +168,7 @@ public class BubbleStackView extends FrameLayout { * Callback to run after the flyout hides. Also called if a new flyout is shown before the * Callback to run after the flyout hides. Also called if a new flyout is shown before the * previous one animates out. * previous one animates out. */ */ private Runnable mAfterFlyoutHides; private Runnable mFlyoutOnHide; /** Layout change listener that moves the stack to the nearest valid position on rotation. */ /** Layout change listener that moves the stack to the nearest valid position on rotation. */ private OnLayoutChangeListener mOrientationChangedListener; private OnLayoutChangeListener mOrientationChangedListener; Loading Loading @@ -1366,73 +1366,48 @@ public class BubbleStackView extends FrameLayout { @VisibleForTesting @VisibleForTesting void animateInFlyoutForBubble(Bubble bubble) { void animateInFlyoutForBubble(Bubble bubble) { final CharSequence updateMessage = bubble.getUpdateMessage(getContext()); final CharSequence updateMessage = bubble.getUpdateMessage(getContext()); if (!bubble.showFlyoutForBubble()) { if (!bubble.showFlyoutForBubble()) { // In case flyout was suppressed for this update, reset now. // In case flyout was suppressed for this update, reset now. bubble.setSuppressFlyout(false); bubble.setSuppressFlyout(false); return; return; } } if (updateMessage == null if (updateMessage == null || isExpanded() || isExpanded() || mIsExpansionAnimating || mIsExpansionAnimating || mIsGestureInProgress || mIsGestureInProgress || mBubbleToExpandAfterFlyoutCollapse != null) { || mBubbleToExpandAfterFlyoutCollapse != null || bubble.getIconView() == null) { // Skip the message if none exists, we're expanded or animating expansion, or we're // 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; 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; mFlyoutDragDeltaX = 0f; clearFlyoutOnHide(); if (mAfterFlyoutHides != null) { mFlyoutOnHide = () -> { mAfterFlyoutHides.run(); 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.setSelectedBubble(mBubbleToExpandAfterFlyoutCollapse); mBubbleData.setExpanded(true); mBubbleData.setExpanded(true); mBubbleToExpandAfterFlyoutCollapse = null; mBubbleToExpandAfterFlyoutCollapse = null; } }; }; mFlyout.setVisibility(INVISIBLE); mFlyout.setVisibility(INVISIBLE); // Post in case layout isn't complete and getWidth returns 0. // 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(() -> { post(() -> { // An auto-expanding bubble could have been posted during the time it takes to // An auto-expanding bubble could have been posted during the time it takes to // layout. // layout. if (isExpanded()) { if (isExpanded()) { return; return; } } final Runnable expandFlyoutAfterDelay = () -> { final Runnable afterShow = () -> { mAnimateInFlyout = () -> { mAnimateInFlyout = () -> { mFlyout.setVisibility(VISIBLE); mFlyout.setVisibility(VISIBLE); bubble.getIconView().setSuppressDot( true /* suppressDot */, false /* animate */); mFlyoutDragDeltaX = mFlyoutDragDeltaX = mStackAnimationController.isStackOnLeftSide() mStackAnimationController.isStackOnLeftSide() ? -mFlyout.getWidth() ? -mFlyout.getWidth() Loading @@ -1440,37 +1415,57 @@ public class BubbleStackView extends FrameLayout { animateFlyoutCollapsed(false /* collapsed */, 0 /* velX */); animateFlyoutCollapsed(false /* collapsed */, 0 /* velX */); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); }; }; mFlyout.postDelayed(mAnimateInFlyout, 200); mFlyout.postDelayed(mAnimateInFlyout, 200); }; }; mFlyout.setupFlyoutStartingAsDot( mFlyout.setupFlyoutStartingAsDot( updateMessage, mStackAnimationController.getStackPosition(), getWidth(), updateMessage, mStackAnimationController.getStackPosition(), getWidth(), mStackAnimationController.isStackOnLeftSide(), mStackAnimationController.isStackOnLeftSide(), bubble.getIconView().getBadgeColor(), bubble.getIconView().getBadgeColor() /* dotColor */, afterShow, expandFlyoutAfterDelay /* onLayoutComplete */, mAfterFlyoutHides, mFlyoutOnHide, bubble.getIconView().getDotCenter()); bubble.getIconView().getDotCenter()); mFlyout.bringToFront(); mFlyout.bringToFront(); }); }); } mFlyout.removeCallbacks(mHideFlyout); mFlyout.removeCallbacks(mHideFlyout); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__FLYOUT); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__FLYOUT); } } /** Hide the flyout immediately and cancel any pending hide runnables. */ private void resetDot(Bubble bubble) { private void hideFlyoutImmediate() { final boolean suppressDot = !bubble.showBubbleDot(); if (mAfterFlyoutHides != null) { // If we're going to suppress the dot, make it visible first so it'll mAfterFlyoutHides.run(); // 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(mAnimateInFlyout); mFlyout.removeCallbacks(mHideFlyout); mFlyout.removeCallbacks(mHideFlyout); mFlyout.hideFlyout(); mFlyout.hideFlyout(); } } private void clearFlyoutOnHide() { mFlyout.removeCallbacks(mAnimateInFlyout); if (mFlyoutOnHide == null) { return; } mFlyoutOnHide.run(); mFlyoutOnHide = null; } @Override @Override public void getBoundsOnScreen(Rect outRect) { public void getBoundsOnScreen(Rect outRect) { if (!mIsExpanded) { if (!mIsExpanded) { Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java +28 −26 Original line number Original line Diff line number Diff line Loading @@ -61,7 +61,7 @@ public class BubbleView extends FrameLayout { // mBubbleIconFactory cannot be static because it depends on Context. // mBubbleIconFactory cannot be static because it depends on Context. private BubbleIconFactory mBubbleIconFactory; private BubbleIconFactory mBubbleIconFactory; private boolean mSuppressDot = false; private boolean mSuppressDot; private Bubble mBubble; private Bubble mBubble; Loading Loading @@ -140,6 +140,7 @@ public class BubbleView extends FrameLayout { public void setAppIcon(Drawable appIcon) { public void setAppIcon(Drawable appIcon) { mUserBadgedAppIcon = appIcon; mUserBadgedAppIcon = appIcon; } } /** /** * @return the {@link ExpandableNotificationRow} view to display notification content when the * @return the {@link ExpandableNotificationRow} view to display notification content when the * bubble is expanded. * bubble is expanded. Loading @@ -154,7 +155,6 @@ public class BubbleView extends FrameLayout { updateDotVisibility(animate, null /* after */); updateDotVisibility(animate, null /* after */); } } /** /** * Sets whether or not to hide the dot even if we'd otherwise show it. This is used while the * 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. * flyout is visible or animating, to hide the dot until the flyout visually transforms into it. Loading @@ -166,7 +166,7 @@ public class BubbleView extends FrameLayout { /** Sets the position of the 'new' dot, animating it out and back in if requested. */ /** Sets the position of the 'new' dot, animating it out and back in if requested. */ void setDotPosition(boolean onLeft, boolean animate) { void setDotPosition(boolean onLeft, boolean animate) { if (animate && onLeft != mBadgedImageView.getDotOnLeft() && !mSuppressDot) { if (animate && onLeft != mBadgedImageView.getDotOnLeft() && shouldShowDot()) { animateDot(false /* showDot */, () -> { animateDot(false /* showDot */, () -> { mBadgedImageView.setDotOnLeft(onLeft); mBadgedImageView.setDotOnLeft(onLeft); animateDot(true /* showDot */, null); animateDot(true /* showDot */, null); Loading @@ -190,12 +190,12 @@ public class BubbleView extends FrameLayout { * after animation if requested. * after animation if requested. */ */ private void updateDotVisibility(boolean animate, Runnable after) { private void updateDotVisibility(boolean animate, Runnable after) { boolean showDot = mBubble.showBubbleDot() && !mSuppressDot; final boolean showDot = shouldShowDot(); if (animate) { if (animate) { animateDot(showDot, after); animateDot(showDot, after); } else { } else { mBadgedImageView.setShowDot(showDot); mBadgedImageView.setShowDot(showDot); mBadgedImageView.setDotScale(showDot ? 1f : 0f); } } } } Loading @@ -203,10 +203,12 @@ public class BubbleView extends FrameLayout { * Animates the badge to show or hide. * Animates the badge to show or hide. */ */ private void animateDot(boolean showDot, Runnable after) { private void animateDot(boolean showDot, Runnable after) { if (mBadgedImageView.isShowingDot() != showDot) { if (mBadgedImageView.isShowingDot() == showDot) { if (showDot) { return; mBadgedImageView.setShowDot(true); } } // Do NOT wait until after animation ends to setShowDot // to avoid overriding more recent showDot states. mBadgedImageView.setShowDot(showDot); mBadgedImageView.clearAnimation(); mBadgedImageView.clearAnimation(); mBadgedImageView.animate().setDuration(200) mBadgedImageView.animate().setDuration(200) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) Loading @@ -215,16 +217,12 @@ public class BubbleView extends FrameLayout { fraction = showDot ? fraction : 1f - fraction; fraction = showDot ? fraction : 1f - fraction; mBadgedImageView.setDotScale(fraction); mBadgedImageView.setDotScale(fraction); }).withEndAction(() -> { }).withEndAction(() -> { if (!showDot) { mBadgedImageView.setDotScale(showDot ? 1f : 0f); mBadgedImageView.setShowDot(false); } if (after != null) { if (after != null) { after.run(); after.run(); } } }).start(); }).start(); } } } void updateViews() { void updateViews() { if (mBubble == null || mBubbleIconFactory == null) { if (mBubble == null || mBubbleIconFactory == null) { Loading Loading @@ -273,7 +271,11 @@ public class BubbleView extends FrameLayout { iconPath.transform(matrix); iconPath.transform(matrix); mBadgedImageView.drawDot(iconPath); mBadgedImageView.drawDot(iconPath); animateDot(mBubble.showBubbleDot() /* showDot */, null /* after */); animateDot(shouldShowDot(), null /* after */); } boolean shouldShowDot() { return mBubble.showBubbleDot() && !mSuppressDot; } } int getBadgeColor() { int getBadgeColor() { Loading