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
This commit is contained in:
Selim Cinek
2016-12-05 17:12:09 -08:00
parent 17e1b69523
commit 932005db01
2 changed files with 61 additions and 9 deletions

View File

@@ -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) {

View File

@@ -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<View, IconState> 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;