From 932005db01cb8ac8506b5b766a9f80faa2c99e41 Mon Sep 17 00:00:00 2001 From: Selim Cinek Date: Mon, 5 Dec 2016 17:12:09 -0800 Subject: [PATCH] Placed the overflow indicator perfectly in the collapsed center Previously, the state could be abitrary based on the width of the layout this is now fixed. Test: add high, low-priority notifications, observe perfect centering Bug: 32437839 Change-Id: Id82d4aa87fe07f53bfe1b891a1ce2caa88d686dc --- .../systemui/statusbar/NotificationShelf.java | 11 +++- .../phone/NotificationIconContainer.java | 59 ++++++++++++++++--- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 8ede78b1d9e56..86c674fec43bf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -471,7 +471,15 @@ public class NotificationShelf extends ActivatableNotificationView { mShelfIcons.getWidth(), openedAmount); mShelfIcons.setActualLayoutWidth(width); - float padding = NotificationUtils.interpolate(mCollapsedIcons.getPaddingEnd(), + boolean hasOverflow = mCollapsedIcons.hasOverflow(); + int collapsedPadding = mCollapsedIcons.getPaddingEnd(); + if (!hasOverflow) { + // we have to ensure that adding the low priority notification won't lead to an + // overflow + collapsedPadding -= (1.0f + NotificationIconContainer.OVERFLOW_EARLY_AMOUNT) + * mCollapsedIcons.getIconSize(); + } + float padding = NotificationUtils.interpolate(collapsedPadding, mShelfIcons.getPaddingEnd(), openedAmount); mShelfIcons.setActualPaddingEnd(padding); @@ -479,6 +487,7 @@ public class NotificationShelf extends ActivatableNotificationView { mShelfIcons.getPaddingStart(), openedAmount); mShelfIcons.setActualPaddingStart(paddingStart); mShelfIcons.setOpenedAmount(openedAmount); + mShelfIcons.setVisualOverflowAdaption(mCollapsedIcons.getVisualOverflowAdaption()); } public void setMaxLayoutHeight(int maxLayoutHeight) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java index a1a8575d733b0..203d6896afb63 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -38,6 +38,13 @@ import java.util.HashMap; * correctly on the screen. */ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { + /** + * A float value indicating how much before the overflow start the icons should transform into + * a dot. A value of 0 means that they are exactly at the end and a value of 1 means it starts + * 1 icon width early. + */ + public static final float OVERFLOW_EARLY_AMOUNT = 0.2f; + private static final int NO_VALUE = Integer.MIN_VALUE; private static final String TAG = "NotificationIconContainer"; private static final boolean DEBUG = false; private static final int CANNED_ANIMATION_DURATION = 100; @@ -83,15 +90,16 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { private final HashMap mIconStates = new HashMap<>(); private int mDotPadding; private int mStaticDotRadius; - private int mActualLayoutWidth = -1; - private float mActualPaddingEnd = -1; - private float mActualPaddingStart = -1; + private int mActualLayoutWidth = NO_VALUE; + private float mActualPaddingEnd = NO_VALUE; + private float mActualPaddingStart = NO_VALUE; private boolean mChangingViewPositions; private int mAddAnimationStartIndex = -1; private int mCannedAnimationStartIndex = -1; private int mSpeedBumpIndex = -1; private int mIconSize; private float mOpenedAmount = 0.0f; + private float mVisualOverflowAdaption; public NotificationIconContainer(Context context, AttributeSet attrs) { super(context, attrs); @@ -226,7 +234,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { int firstOverflowIndex = -1; int childCount = getChildCount(); float layoutEnd = getLayoutEnd(); - float overflowStart = layoutEnd - mIconSize * 2.2f; + float overflowStart = layoutEnd - mIconSize * (2 + OVERFLOW_EARLY_AMOUNT); boolean hasAmbient = mSpeedBumpIndex != -1 && mSpeedBumpIndex < getChildCount(); float visualOverflowStart = 0; for (int i = 0; i < childCount; i++) { @@ -244,7 +252,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { || (translationX >= (noOverflowAfter ? layoutEnd - mIconSize : overflowStart)))) { firstOverflowIndex = noOverflowAfter ? i - 1 : i; int totalDotLength = mStaticDotRadius * 6 + 2 * mDotPadding; - visualOverflowStart = overflowStart + mIconSize * 1.2f - totalDotLength / 2 + visualOverflowStart = overflowStart + mIconSize * (1 + OVERFLOW_EARLY_AMOUNT) + - totalDotLength / 2 - mIconSize * 0.5f + mStaticDotRadius; if (isAmbient) { visualOverflowStart = Math.min(translationX, visualOverflowStart @@ -253,6 +262,23 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { visualOverflowStart += (translationX - overflowStart) / mIconSize * (mStaticDotRadius * 2 + mDotPadding); } + if (mShowAllIcons) { + // We want to perfectly position the overflow in the static state, such that + // it's perfectly centered instead of measuring it from the end. + mVisualOverflowAdaption = 0; + if (firstOverflowIndex != -1) { + View firstOverflowView = getChildAt(i); + IconState overflowState = mIconStates.get(firstOverflowView); + float totalAmount = layoutEnd - overflowState.xTranslation; + float newPosition = overflowState.xTranslation + totalAmount / 2 + - totalDotLength / 2 + - mIconSize * 0.5f + mStaticDotRadius; + mVisualOverflowAdaption = newPosition - visualOverflowStart; + visualOverflowStart = newPosition; + } + } else { + visualOverflowStart += mVisualOverflowAdaption * (1f - mOpenedAmount); + } } translationX += iconState.iconAppearAmount * view.getWidth(); } @@ -293,14 +319,14 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { } private float getActualPaddingEnd() { - if (mActualPaddingEnd < 0) { + if (mActualPaddingEnd == NO_VALUE) { return getPaddingEnd(); } return mActualPaddingEnd; } private float getActualPaddingStart() { - if (mActualPaddingStart < 0) { + if (mActualPaddingStart == NO_VALUE) { return getPaddingStart(); } return mActualPaddingStart; @@ -338,7 +364,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { } public int getActualWidth() { - if (mActualLayoutWidth < 0) { + if (mActualLayoutWidth == NO_VALUE) { return getWidth(); } return mActualLayoutWidth; @@ -360,6 +386,23 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { mOpenedAmount = expandAmount; } + public float getVisualOverflowAdaption() { + return mVisualOverflowAdaption; + } + + public void setVisualOverflowAdaption(float visualOverflowAdaption) { + mVisualOverflowAdaption = visualOverflowAdaption; + } + + public boolean hasOverflow() { + float width = (getChildCount() + OVERFLOW_EARLY_AMOUNT) * mIconSize; + return width - (getWidth() - getActualPaddingStart() - getActualPaddingEnd()) > 0; + } + + public int getIconSize() { + return mIconSize; + } + public class IconState extends ViewState { public float iconAppearAmount = 1.0f; public float clampedAppearAmount = 1.0f;