Merge "Fix notification shelf issues" into tm-dev
This commit is contained in:
@@ -39,7 +39,6 @@ import com.android.systemui.statusbar.notification.NotificationUtils;
|
|||||||
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
|
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
||||||
import com.android.systemui.statusbar.notification.row.NotificationBackgroundView;
|
|
||||||
import com.android.systemui.statusbar.notification.stack.AmbientState;
|
import com.android.systemui.statusbar.notification.stack.AmbientState;
|
||||||
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
||||||
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
|
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
|
||||||
@@ -411,7 +410,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
|||||||
setBackgroundTop(backgroundTop);
|
setBackgroundTop(backgroundTop);
|
||||||
setFirstElementRoundness(firstElementRoundness);
|
setFirstElementRoundness(firstElementRoundness);
|
||||||
mShelfIcons.setSpeedBumpIndex(mHostLayoutController.getSpeedBumpIndex());
|
mShelfIcons.setSpeedBumpIndex(mHostLayoutController.getSpeedBumpIndex());
|
||||||
mShelfIcons.calculateIconTranslations();
|
mShelfIcons.calculateIconXTranslations();
|
||||||
mShelfIcons.applyIconStates();
|
mShelfIcons.applyIconStates();
|
||||||
for (int i = 0; i < mHostLayoutController.getChildCount(); i++) {
|
for (int i = 0; i < mHostLayoutController.getChildCount(); i++) {
|
||||||
View child = mHostLayoutController.getChildAt(i);
|
View child = mHostLayoutController.getChildAt(i);
|
||||||
@@ -636,7 +635,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
|||||||
float viewEnd = viewStart + fullHeight;
|
float viewEnd = viewStart + fullHeight;
|
||||||
float fullTransitionAmount = 0.0f;
|
float fullTransitionAmount = 0.0f;
|
||||||
float iconTransitionAmount = 0.0f;
|
float iconTransitionAmount = 0.0f;
|
||||||
float shelfStart = getTranslationY();
|
float shelfStart = getTranslationY() - mPaddingBetweenElements;
|
||||||
if (mAmbientState.isExpansionChanging() && !mAmbientState.isOnKeyguard()) {
|
if (mAmbientState.isExpansionChanging() && !mAmbientState.isOnKeyguard()) {
|
||||||
// TODO(b/172289889) handle icon placement for notification that is clipped by the shelf
|
// TODO(b/172289889) handle icon placement for notification that is clipped by the shelf
|
||||||
if (mIndexOfFirstViewInShelf != -1 && i >= mIndexOfFirstViewInShelf) {
|
if (mIndexOfFirstViewInShelf != -1 && i >= mIndexOfFirstViewInShelf) {
|
||||||
|
|||||||
@@ -207,9 +207,7 @@ constructor(
|
|||||||
visibleIndex: Int
|
visibleIndex: Int
|
||||||
): Float {
|
): Float {
|
||||||
var height = stack.calculateGapHeight(previous, current, visibleIndex)
|
var height = stack.calculateGapHeight(previous, current, visibleIndex)
|
||||||
if (visibleIndex != 0) {
|
height += dividerHeight
|
||||||
height += dividerHeight
|
|
||||||
}
|
|
||||||
return height
|
return height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -314,7 +314,8 @@ public class StackScrollAlgorithm {
|
|||||||
|
|
||||||
if (ambientState.getShelf() != null) {
|
if (ambientState.getShelf() != null) {
|
||||||
final float shelfStart = ambientState.getStackEndHeight()
|
final float shelfStart = ambientState.getStackEndHeight()
|
||||||
- ambientState.getShelf().getIntrinsicHeight();
|
- ambientState.getShelf().getIntrinsicHeight()
|
||||||
|
- mPaddingBetweenElements;
|
||||||
if (currentY >= shelfStart
|
if (currentY >= shelfStart
|
||||||
&& !(view instanceof FooterView)
|
&& !(view instanceof FooterView)
|
||||||
&& state.firstViewInShelf == null) {
|
&& state.firstViewInShelf == null) {
|
||||||
@@ -507,8 +508,9 @@ public class StackScrollAlgorithm {
|
|||||||
|| bypassPulseNotExpanding
|
|| bypassPulseNotExpanding
|
||||||
? ambientState.getInnerHeight()
|
? ambientState.getInnerHeight()
|
||||||
: (int) ambientState.getStackHeight();
|
: (int) ambientState.getStackHeight();
|
||||||
final int shelfStart =
|
final int shelfStart = stackBottom
|
||||||
stackBottom - ambientState.getShelf().getIntrinsicHeight();
|
- ambientState.getShelf().getIntrinsicHeight()
|
||||||
|
- mPaddingBetweenElements;
|
||||||
viewState.yTranslation = Math.min(viewState.yTranslation, shelfStart);
|
viewState.yTranslation = Math.min(viewState.yTranslation, shelfStart);
|
||||||
if (viewState.yTranslation >= shelfStart) {
|
if (viewState.yTranslation >= shelfStart) {
|
||||||
viewState.hidden = !view.isExpandAnimationRunning()
|
viewState.hidden = !view.isExpandAnimationRunning()
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ import android.graphics.Paint;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.MathUtils;
|
||||||
import android.util.Property;
|
import android.util.Property;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.collection.ArrayMap;
|
import androidx.collection.ArrayMap;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
@@ -136,6 +138,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
}.setDuration(CONTENT_FADE_DURATION);
|
}.setDuration(CONTENT_FADE_DURATION);
|
||||||
|
|
||||||
private static final int MAX_ICONS_ON_AOD = 3;
|
private static final int MAX_ICONS_ON_AOD = 3;
|
||||||
|
|
||||||
|
/* Maximum number of icons in short shelf on lockscreen when also showing overflow dot. */
|
||||||
public static final int MAX_ICONS_ON_LOCKSCREEN = 3;
|
public static final int MAX_ICONS_ON_LOCKSCREEN = 3;
|
||||||
public static final int MAX_STATIC_ICONS = 4;
|
public static final int MAX_STATIC_ICONS = 4;
|
||||||
private static final int MAX_DOTS = 1;
|
private static final int MAX_DOTS = 1;
|
||||||
@@ -145,7 +149,6 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
private int mDotPadding;
|
private int mDotPadding;
|
||||||
private int mStaticDotRadius;
|
private int mStaticDotRadius;
|
||||||
private int mStaticDotDiameter;
|
private int mStaticDotDiameter;
|
||||||
private int mOverflowWidth;
|
|
||||||
private int mActualLayoutWidth = NO_VALUE;
|
private int mActualLayoutWidth = NO_VALUE;
|
||||||
private float mActualPaddingEnd = NO_VALUE;
|
private float mActualPaddingEnd = NO_VALUE;
|
||||||
private float mActualPaddingStart = NO_VALUE;
|
private float mActualPaddingStart = NO_VALUE;
|
||||||
@@ -219,10 +222,6 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
|
|
||||||
paint.setColor(Color.RED);
|
paint.setColor(Color.RED);
|
||||||
canvas.drawLine(mVisualOverflowStart, 0, mVisualOverflowStart, height, paint);
|
canvas.drawLine(mVisualOverflowStart, 0, mVisualOverflowStart, height, paint);
|
||||||
|
|
||||||
paint.setColor(Color.YELLOW);
|
|
||||||
float overflow = getMaxOverflowStart();
|
|
||||||
canvas.drawLine(overflow, 0, overflow, height, paint);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,14 +254,14 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setIconSize(int size) {
|
@VisibleForTesting
|
||||||
|
public void setIconSize(int size) {
|
||||||
mIconSize = size;
|
mIconSize = size;
|
||||||
mOverflowWidth = mIconSize + (MAX_DOTS - 1) * (mStaticDotDiameter + mDotPadding);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateState() {
|
private void updateState() {
|
||||||
resetViewStates();
|
resetViewStates();
|
||||||
calculateIconTranslations();
|
calculateIconXTranslations();
|
||||||
applyIconStates();
|
applyIconStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,12 +389,11 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
* @return Width of shelf for the given number of icons
|
* @return Width of shelf for the given number of icons
|
||||||
*/
|
*/
|
||||||
public float calculateWidthFor(float numIcons) {
|
public float calculateWidthFor(float numIcons) {
|
||||||
if (getChildCount() == 0) {
|
if (numIcons == 0) {
|
||||||
return 0f;
|
return 0f;
|
||||||
}
|
}
|
||||||
final float contentWidth = numIcons <= MAX_ICONS_ON_LOCKSCREEN + 1
|
final float contentWidth =
|
||||||
? numIcons * mIconSize
|
mIconSize * MathUtils.min(numIcons, MAX_ICONS_ON_LOCKSCREEN + 1);
|
||||||
: MAX_ICONS_ON_LOCKSCREEN * mIconSize + (float) mOverflowWidth;
|
|
||||||
return getActualPaddingStart()
|
return getActualPaddingStart()
|
||||||
+ contentWidth
|
+ contentWidth
|
||||||
+ getActualPaddingEnd();
|
+ getActualPaddingEnd();
|
||||||
@@ -406,14 +404,13 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
* are inserted into the notification container.
|
* are inserted into the notification container.
|
||||||
* If this is not a whole number, the fraction means by how much the icon is appearing.
|
* If this is not a whole number, the fraction means by how much the icon is appearing.
|
||||||
*/
|
*/
|
||||||
public void calculateIconTranslations() {
|
public void calculateIconXTranslations() {
|
||||||
float translationX = getActualPaddingStart();
|
float translationX = getActualPaddingStart();
|
||||||
int firstOverflowIndex = -1;
|
int firstOverflowIndex = -1;
|
||||||
int childCount = getChildCount();
|
int childCount = getChildCount();
|
||||||
int maxVisibleIcons = mOnLockScreen ? MAX_ICONS_ON_AOD :
|
int maxVisibleIcons = mOnLockScreen ? MAX_ICONS_ON_AOD :
|
||||||
mIsStaticLayout ? MAX_STATIC_ICONS : childCount;
|
mIsStaticLayout ? MAX_STATIC_ICONS : childCount;
|
||||||
float layoutEnd = getLayoutEnd();
|
float layoutEnd = getLayoutEnd();
|
||||||
float overflowStart = getMaxOverflowStart();
|
|
||||||
mVisualOverflowStart = 0;
|
mVisualOverflowStart = 0;
|
||||||
mFirstVisibleIconState = null;
|
mFirstVisibleIconState = null;
|
||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
@@ -438,12 +435,12 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
? StatusBarIconView.STATE_HIDDEN
|
? StatusBarIconView.STATE_HIDDEN
|
||||||
: StatusBarIconView.STATE_ICON;
|
: StatusBarIconView.STATE_ICON;
|
||||||
|
|
||||||
boolean isOverflowing =
|
final float overflowDotX = layoutEnd - mIconSize;
|
||||||
(translationX > (isLastChild ? layoutEnd - mIconSize
|
boolean isOverflowing = translationX > overflowDotX;
|
||||||
: overflowStart - mIconSize));
|
|
||||||
if (firstOverflowIndex == -1 && (forceOverflow || isOverflowing)) {
|
if (firstOverflowIndex == -1 && (forceOverflow || isOverflowing)) {
|
||||||
firstOverflowIndex = isLastChild && !forceOverflow ? i - 1 : i;
|
firstOverflowIndex = isLastChild && !forceOverflow ? i - 1 : i;
|
||||||
mVisualOverflowStart = layoutEnd - mOverflowWidth;
|
mVisualOverflowStart = layoutEnd - mIconSize;
|
||||||
if (forceOverflow || mIsStaticLayout) {
|
if (forceOverflow || mIsStaticLayout) {
|
||||||
mVisualOverflowStart = Math.min(translationX, mVisualOverflowStart);
|
mVisualOverflowStart = Math.min(translationX, mVisualOverflowStart);
|
||||||
}
|
}
|
||||||
@@ -477,7 +474,6 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
mLastVisibleIconState = mIconStates.get(lastChild);
|
mLastVisibleIconState = mIconStates.get(lastChild);
|
||||||
mFirstVisibleIconState = mIconStates.get(getChildAt(0));
|
mFirstVisibleIconState = mIconStates.get(getChildAt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLayoutRtl()) {
|
if (isLayoutRtl()) {
|
||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
View view = getChildAt(i);
|
View view = getChildAt(i);
|
||||||
@@ -568,7 +564,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private float getMaxOverflowStart() {
|
private float getMaxOverflowStart() {
|
||||||
return getLayoutEnd() - mOverflowWidth;
|
return getLayoutEnd() - mIconSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChangingViewPositions(boolean changingViewPositions) {
|
public void setChangingViewPositions(boolean changingViewPositions) {
|
||||||
@@ -635,7 +631,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int collapsedPadding = mOverflowWidth;
|
int collapsedPadding = mIconSize;
|
||||||
|
|
||||||
if (collapsedPadding + getFinalTranslationX() > getWidth()) {
|
if (collapsedPadding + getFinalTranslationX() > getWidth()) {
|
||||||
collapsedPadding = getWidth() - getFinalTranslationX();
|
collapsedPadding = getWidth() - getFinalTranslationX();
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
|
|||||||
@Mock private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
|
@Mock private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
|
||||||
@Mock private lateinit var stackLayout: NotificationStackScrollLayout
|
@Mock private lateinit var stackLayout: NotificationStackScrollLayout
|
||||||
|
|
||||||
private val testableResources = mContext.getOrCreateTestableResources()
|
private val testableResources = mContext.orCreateTestableResources
|
||||||
|
|
||||||
private lateinit var sizeCalculator: NotificationStackSizeCalculator
|
private lateinit var sizeCalculator: NotificationStackSizeCalculator
|
||||||
|
|
||||||
@@ -121,17 +121,16 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun computeHeight_returnsAtMostSpaceAvailable_withGapBeforeShelf() {
|
fun computeHeight_gapBeforeShelf_returnsSpaceUsed() {
|
||||||
|
// Each row in separate section.
|
||||||
setGapHeight(gapHeight)
|
setGapHeight(gapHeight)
|
||||||
val shelfHeight = shelfHeight
|
val spaceUsed =
|
||||||
val availableSpace =
|
|
||||||
listOf(
|
listOf(
|
||||||
rowHeight + dividerHeight,
|
dividerHeight + rowHeight,
|
||||||
gapHeight + rowHeight + dividerHeight,
|
dividerHeight + gapHeight + rowHeight,
|
||||||
gapHeight + dividerHeight + shelfHeight)
|
dividerHeight + gapHeight + shelfHeight)
|
||||||
.sum()
|
.sum()
|
||||||
|
val availableSpace = spaceUsed + 1;
|
||||||
// All rows in separate sections (default setup).
|
|
||||||
val rows =
|
val rows =
|
||||||
listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight))
|
listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight))
|
||||||
|
|
||||||
@@ -139,23 +138,29 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
|
|||||||
assertThat(maxNotifications).isEqualTo(2)
|
assertThat(maxNotifications).isEqualTo(2)
|
||||||
|
|
||||||
val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight)
|
val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight)
|
||||||
assertThat(height).isAtMost(availableSpace)
|
assertThat(height).isEqualTo(spaceUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun computeHeight_noGapBeforeShelf_returnsAtMostSpaceAvailable() {
|
fun computeHeight_noGapBeforeShelf_returnsSpaceUsed() {
|
||||||
// Both rows are in the same section.
|
// Both rows are in the same section.
|
||||||
setGapHeight(0f)
|
setGapHeight(0f)
|
||||||
|
|
||||||
val rowHeight = rowHeight
|
val rowHeight = rowHeight
|
||||||
val shelfHeight = shelfHeight
|
val shelfHeight = shelfHeight
|
||||||
val availableSpace = listOf(rowHeight + dividerHeight, dividerHeight + shelfHeight).sum()
|
val spaceUsed =
|
||||||
|
listOf(
|
||||||
|
dividerHeight + rowHeight,
|
||||||
|
dividerHeight + shelfHeight)
|
||||||
|
.sum()
|
||||||
|
val availableSpace = spaceUsed + 1
|
||||||
val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight))
|
val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight))
|
||||||
|
|
||||||
val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight)
|
val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight)
|
||||||
assertThat(maxNotifications).isEqualTo(1)
|
assertThat(maxNotifications).isEqualTo(1)
|
||||||
|
|
||||||
val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight)
|
val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight)
|
||||||
assertThat(height).isAtMost(availableSpace)
|
assertThat(height).isEqualTo(spaceUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -190,7 +195,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0,
|
val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0,
|
||||||
previousView = null, stack = stackLayout, onLockscreen = true)
|
previousView = null, stack = stackLayout, onLockscreen = true)
|
||||||
assertThat(space).isEqualTo(5)
|
assertThat(space).isEqualTo(5 + dividerHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -204,7 +209,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0,
|
val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0,
|
||||||
previousView = null, stack = stackLayout, onLockscreen = false)
|
previousView = null, stack = stackLayout, onLockscreen = false)
|
||||||
assertThat(space).isEqualTo(10)
|
assertThat(space).isEqualTo(10 + dividerHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeMaxKeyguardNotifications(
|
private fun computeMaxKeyguardNotifications(
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.systemui.statusbar.phone
|
||||||
|
|
||||||
|
import android.service.notification.StatusBarNotification
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.StatusBarIconView
|
||||||
|
import junit.framework.Assert.assertEquals
|
||||||
|
import junit.framework.Assert.assertFalse
|
||||||
|
import junit.framework.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mockito.mock
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link NotificationIconContainer}.
|
||||||
|
*/
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@RunWithLooper
|
||||||
|
class NotificationIconContainerTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private val iconContainer = NotificationIconContainer(context, /* attrs= */ null)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun calculateWidthFor_zeroIcons_widthIsZero() {
|
||||||
|
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 0f),
|
||||||
|
/* actual= */ 0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun calculateWidthFor_oneIcon_widthForOneIcon() {
|
||||||
|
iconContainer.setActualPaddingStart(10f)
|
||||||
|
iconContainer.setActualPaddingEnd(10f)
|
||||||
|
iconContainer.setIconSize(10);
|
||||||
|
|
||||||
|
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 1f),
|
||||||
|
/* actual= */ 30f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun calculateWidthFor_fourIcons_widthForFourIcons() {
|
||||||
|
iconContainer.setActualPaddingStart(10f)
|
||||||
|
iconContainer.setActualPaddingEnd(10f)
|
||||||
|
iconContainer.setIconSize(10);
|
||||||
|
|
||||||
|
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 4f),
|
||||||
|
/* actual= */ 60f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun calculateWidthFor_fiveIcons_widthForFourIcons() {
|
||||||
|
iconContainer.setActualPaddingStart(10f)
|
||||||
|
iconContainer.setActualPaddingEnd(10f)
|
||||||
|
iconContainer.setIconSize(10);
|
||||||
|
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 5f),
|
||||||
|
/* actual= */ 60f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun calculateIconXTranslations_shortShelfOneIcon_atCorrectXWithoutOverflowDot() {
|
||||||
|
iconContainer.setActualPaddingStart(10f)
|
||||||
|
iconContainer.setActualPaddingEnd(10f)
|
||||||
|
iconContainer.setIconSize(10);
|
||||||
|
|
||||||
|
val icon = mockStatusBarIcon()
|
||||||
|
iconContainer.addView(icon)
|
||||||
|
assertEquals(1, iconContainer.childCount)
|
||||||
|
|
||||||
|
val iconState = iconContainer.getIconState(icon)
|
||||||
|
iconState.iconAppearAmount = 1f
|
||||||
|
|
||||||
|
val width = iconContainer.calculateWidthFor(/* numIcons= */ 1f)
|
||||||
|
iconContainer.setActualLayoutWidth(width.toInt())
|
||||||
|
|
||||||
|
iconContainer.calculateIconXTranslations()
|
||||||
|
assertEquals(10f, iconState.xTranslation)
|
||||||
|
assertFalse(iconContainer.hasOverflow())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun calculateIconXTranslations_shortShelfFourIcons_atCorrectXWithoutOverflowDot() {
|
||||||
|
iconContainer.setActualPaddingStart(10f)
|
||||||
|
iconContainer.setActualPaddingEnd(10f)
|
||||||
|
iconContainer.setIconSize(10);
|
||||||
|
|
||||||
|
val iconOne = mockStatusBarIcon()
|
||||||
|
val iconTwo = mockStatusBarIcon()
|
||||||
|
val iconThree = mockStatusBarIcon()
|
||||||
|
val iconFour = mockStatusBarIcon()
|
||||||
|
|
||||||
|
iconContainer.addView(iconOne)
|
||||||
|
iconContainer.addView(iconTwo)
|
||||||
|
iconContainer.addView(iconThree)
|
||||||
|
iconContainer.addView(iconFour)
|
||||||
|
assertEquals(4, iconContainer.childCount)
|
||||||
|
|
||||||
|
val width = iconContainer.calculateWidthFor(/* numIcons= */ 4f)
|
||||||
|
iconContainer.setActualLayoutWidth(width.toInt())
|
||||||
|
|
||||||
|
iconContainer.calculateIconXTranslations()
|
||||||
|
assertEquals(10f, iconContainer.getIconState(iconOne).xTranslation)
|
||||||
|
assertEquals(20f, iconContainer.getIconState(iconTwo).xTranslation)
|
||||||
|
assertEquals(30f, iconContainer.getIconState(iconThree).xTranslation)
|
||||||
|
assertEquals(40f, iconContainer.getIconState(iconFour).xTranslation)
|
||||||
|
|
||||||
|
assertFalse(iconContainer.hasOverflow())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun calculateIconXTranslations_shortShelfFiveIcons_atCorrectXWithOverflowDot() {
|
||||||
|
iconContainer.setActualPaddingStart(10f)
|
||||||
|
iconContainer.setActualPaddingEnd(10f)
|
||||||
|
iconContainer.setIconSize(10);
|
||||||
|
|
||||||
|
val iconOne = mockStatusBarIcon()
|
||||||
|
val iconTwo = mockStatusBarIcon()
|
||||||
|
val iconThree = mockStatusBarIcon()
|
||||||
|
val iconFour = mockStatusBarIcon()
|
||||||
|
val iconFive = mockStatusBarIcon()
|
||||||
|
|
||||||
|
iconContainer.addView(iconOne)
|
||||||
|
iconContainer.addView(iconTwo)
|
||||||
|
iconContainer.addView(iconThree)
|
||||||
|
iconContainer.addView(iconFour)
|
||||||
|
iconContainer.addView(iconFive)
|
||||||
|
assertEquals(5, iconContainer.childCount)
|
||||||
|
|
||||||
|
val width = iconContainer.calculateWidthFor(/* numIcons= */ 5f)
|
||||||
|
iconContainer.setActualLayoutWidth(width.toInt())
|
||||||
|
|
||||||
|
iconContainer.calculateIconXTranslations()
|
||||||
|
assertEquals(10f, iconContainer.getIconState(iconOne).xTranslation)
|
||||||
|
assertEquals(20f, iconContainer.getIconState(iconTwo).xTranslation)
|
||||||
|
assertEquals(30f, iconContainer.getIconState(iconThree).xTranslation)
|
||||||
|
assertTrue(iconContainer.hasOverflow())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mockStatusBarIcon() : StatusBarIconView {
|
||||||
|
val iconView = mock(StatusBarIconView::class.java)
|
||||||
|
whenever(iconView.width).thenReturn(10)
|
||||||
|
|
||||||
|
val icon = mock(android.graphics.drawable.Icon::class.java)
|
||||||
|
whenever(iconView.sourceIcon).thenReturn(icon)
|
||||||
|
|
||||||
|
val sbn = mock(StatusBarNotification::class.java)
|
||||||
|
whenever(sbn.groupKey).thenReturn("groupKey")
|
||||||
|
whenever(iconView.notification).thenReturn(sbn)
|
||||||
|
return iconView
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user