Merge changes If1a0855e,I5a079522 into udc-qpr-dev

* changes:
  fix(non linear font scaling): fix QQS clock text right padding may not proper when font sclaing changed
  fix(non linear font scaling): fix status bar icons and dot be cut off or wrong posistion
This commit is contained in:
Roy Chou
2023-07-11 11:52:51 +00:00
committed by Android (Google) Code Review
5 changed files with 112 additions and 21 deletions

View File

@@ -275,6 +275,7 @@ constructor(
lastInsets?.let { updateConstraintsForInsets(header, it) }
updateResources()
updateCarrierGroupPadding()
clock.onDensityOrFontScaleChanged()
}
}

View File

@@ -448,9 +448,14 @@ public class NotificationIconContainer extends ViewGroup {
@VisibleForTesting
boolean isOverflowing(boolean isLastChild, float translationX, float layoutEnd,
float iconSize) {
// Layout end, as used here, does not include padding end.
final float overflowX = isLastChild ? layoutEnd : layoutEnd - iconSize;
return translationX >= overflowX;
if (isLastChild) {
return translationX + iconSize > layoutEnd;
} else {
// If the child is not the last child, we need to ensure that we have room for the next
// icon and the dot. The dot could be as large as an icon, so verify that we have room
// for 2 icons.
return translationX + iconSize * 2f > layoutEnd;
}
}
/**
@@ -490,10 +495,7 @@ public class NotificationIconContainer extends ViewGroup {
// First icon to overflow.
if (firstOverflowIndex == -1 && isOverflowing) {
firstOverflowIndex = i;
mVisualOverflowStart = layoutEnd - mIconSize;
if (forceOverflow || mIsStaticLayout) {
mVisualOverflowStart = Math.min(translationX, mVisualOverflowStart);
}
mVisualOverflowStart = translationX;
}
final float drawingScale = mOnLockScreen && view instanceof StatusBarIconView
? ((StatusBarIconView) view).getIconScaleIncreased()

View File

@@ -22,6 +22,8 @@ import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@@ -73,13 +75,16 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
// Any ignored icon will never be added as a child
private ArrayList<String> mIgnoredSlots = new ArrayList<>();
private Configuration mConfiguration;
public StatusIconContainer(Context context) {
this(context, null);
}
public StatusIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
initDimens();
mConfiguration = new Configuration(context.getResources().getConfiguration());
reloadDimens();
setWillNotDraw(!DEBUG_OVERFLOW);
}
@@ -100,7 +105,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
return mShouldRestrictIcons;
}
private void initDimens() {
private void reloadDimens() {
// This is the same value that StatusBarIconView uses
mIconDotFrameWidth = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_icon_size_sp);
@@ -233,6 +238,16 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
child.setTag(R.id.status_bar_view_state_tag, null);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
final int configDiff = newConfig.diff(mConfiguration);
mConfiguration.setTo(newConfig);
if ((configDiff & (ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_FONT_SCALE)) != 0) {
reloadDimens();
}
}
/**
* Add a name of an icon slot to be ignored. It will not show up nor be measured
* @param slotName name of the icon as it exists in
@@ -342,13 +357,17 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
int totalVisible = mLayoutStates.size();
int maxVisible = totalVisible <= MAX_ICONS ? MAX_ICONS : MAX_ICONS - 1;
mUnderflowStart = 0;
// Init mUnderflowStart value with the offset to let the dot be placed next to battery icon.
// This is to prevent if the underflow happens at rightest(totalVisible - 1) child then
// break the for loop with mUnderflowStart staying 0(initial value), causing the dot be
// placed at the leftest side.
mUnderflowStart = (int) Math.max(contentStart, width - getPaddingEnd() - mUnderflowWidth);
int visible = 0;
int firstUnderflowIndex = -1;
for (int i = totalVisible - 1; i >= 0; i--) {
StatusIconState state = mLayoutStates.get(i);
// Allow room for underflow if we found we need it in onMeasure
if (mNeedsUnderflow && (state.getXTranslation() < (contentStart + mUnderflowWidth))
if ((mNeedsUnderflow && (state.getXTranslation() < (contentStart + mUnderflowWidth)))
|| (mShouldRestrictIcons && (visible >= maxVisible))) {
firstUnderflowIndex = i;
break;

View File

@@ -374,6 +374,13 @@ public class Clock extends TextView implements
@Override
public void onDensityOrFontScaleChanged() {
reloadDimens();
}
private void reloadDimens() {
// reset mCachedWidth so the new width would be updated properly when next onMeasure
mCachedWidth = -1;
FontSizeUtils.updateFontSize(this, R.dimen.status_bar_clock_size);
setPaddingRelative(
mContext.getResources().getDimensionPixelSize(

View File

@@ -21,6 +21,8 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
@@ -49,7 +51,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateWidthFor_oneIcon_widthForOneIcon() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
iconContainer.setIconSize(10);
iconContainer.setIconSize(10)
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 1f),
/* actual= */ 30f)
@@ -59,7 +61,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateWidthFor_fourIcons_widthForFourIcons() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
iconContainer.setIconSize(10);
iconContainer.setIconSize(10)
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 4f),
/* actual= */ 60f)
@@ -69,7 +71,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateWidthFor_fiveIcons_widthForFourIcons() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
iconContainer.setIconSize(10);
iconContainer.setIconSize(10)
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 5f),
/* actual= */ 60f)
}
@@ -78,7 +80,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateIconXTranslations_shortShelfOneIcon_atCorrectXWithoutOverflowDot() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
iconContainer.setIconSize(10);
iconContainer.setIconSize(10)
val icon = mockStatusBarIcon()
iconContainer.addView(icon)
@@ -99,7 +101,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateIconXTranslations_shortShelfFourIcons_atCorrectXWithoutOverflowDot() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
iconContainer.setIconSize(10);
iconContainer.setIconSize(10)
val iconOne = mockStatusBarIcon()
val iconTwo = mockStatusBarIcon()
@@ -128,7 +130,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateIconXTranslations_shortShelfFiveIcons_atCorrectXWithOverflowDot() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
iconContainer.setIconSize(10);
iconContainer.setIconSize(10)
val iconOne = mockStatusBarIcon()
val iconTwo = mockStatusBarIcon()
@@ -153,6 +155,55 @@ class NotificationIconContainerTest : SysuiTestCase() {
assertTrue(iconContainer.areIconsOverflowing())
}
@Test
fun calculateIconXTranslations_givenWidthEnoughForThreeIcons_atCorrectXWithoutOverflowDot() {
iconContainer.setActualPaddingStart(0f)
iconContainer.setActualPaddingEnd(0f)
iconContainer.setActualLayoutWidth(30)
iconContainer.setIconSize(10)
val iconOne = mockStatusBarIcon()
val iconTwo = mockStatusBarIcon()
val iconThree = mockStatusBarIcon()
iconContainer.addView(iconOne)
iconContainer.addView(iconTwo)
iconContainer.addView(iconThree)
assertEquals(3, iconContainer.childCount)
iconContainer.calculateIconXTranslations()
assertEquals(0f, iconContainer.getIconState(iconOne).xTranslation)
assertEquals(10f, iconContainer.getIconState(iconTwo).xTranslation)
assertEquals(20f, iconContainer.getIconState(iconThree).xTranslation)
assertFalse(iconContainer.areIconsOverflowing())
}
@Test
fun calculateIconXTranslations_givenWidthNotEnoughForFourIcons_atCorrectXWithOverflowDot() {
iconContainer.setActualPaddingStart(0f)
iconContainer.setActualPaddingEnd(0f)
iconContainer.setActualLayoutWidth(35)
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)
iconContainer.calculateIconXTranslations()
assertEquals(0f, iconContainer.getIconState(iconOne).xTranslation)
assertEquals(10f, iconContainer.getIconState(iconTwo).xTranslation)
assertEquals(STATE_DOT, iconContainer.getIconState(iconThree).visibleState)
assertEquals(STATE_HIDDEN, iconContainer.getIconState(iconFour).visibleState)
assertTrue(iconContainer.areIconsOverflowing())
}
@Test
fun shouldForceOverflow_appearingAboveSpeedBump_true() {
val forceOverflow = iconContainer.shouldForceOverflow(
@@ -161,7 +212,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
/* iconAppearAmount= */ 1f,
/* maxVisibleIcons= */ 5
)
assertTrue(forceOverflow);
assertTrue(forceOverflow)
}
@Test
@@ -172,7 +223,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
/* iconAppearAmount= */ 0f,
/* maxVisibleIcons= */ 5
)
assertTrue(forceOverflow);
assertTrue(forceOverflow)
}
@Test
@@ -183,7 +234,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
/* iconAppearAmount= */ 0f,
/* maxVisibleIcons= */ 5
)
assertFalse(forceOverflow);
assertFalse(forceOverflow)
}
@Test
@@ -209,6 +260,17 @@ class NotificationIconContainerTest : SysuiTestCase() {
assertTrue(isOverflowing)
}
@Test
fun isOverflowing_lastChildXGreaterThanDotX_true() {
val isOverflowing = iconContainer.isOverflowing(
/* isLastChild= */ true,
/* translationX= */ 9f,
/* layoutEnd= */ 10f,
/* iconSize= */ 2f,
)
assertTrue(isOverflowing)
}
@Test
fun isOverflowing_lastChildXGreaterThanLayoutEnd_true() {
val isOverflowing = iconContainer.isOverflowing(
@@ -253,7 +315,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
assertTrue(isOverflowing)
}
private fun mockStatusBarIcon() : StatusBarIconView {
private fun mockStatusBarIcon(): StatusBarIconView {
val iconView = mock(StatusBarIconView::class.java)
whenever(iconView.width).thenReturn(10)