fix(non linear font scaling)!: fix QS text being cut off when 200% font scaling
Originally the QS tile height is fixed to 80dp and may contain 2 textViews in tile content. When font scaling changed to 200%, the height from 80dp is not enough for the textViews. Therefore, in TileLayout, we estimate the needed height for the tile under given font scaling, and compare with the height from resources/dimens. The larger height would become the exact tile height, to have a proper tile height for full tile content view.
Bug: b/272072639
Test: manually - attached video in bug
atest TileLayoutTest
atest QuickQSPanelTest
Change-Id: I6054ef1a6fd0fc28522181f5bc7774cb0abaf14a
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 46724ad..d889979 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -24,6 +24,7 @@
import android.widget.LinearLayout;
import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
@@ -198,13 +199,23 @@
@Override
public boolean updateResources() {
- mCellHeightResId = R.dimen.qs_quick_tile_size;
+ mResourceCellHeightResId = R.dimen.qs_quick_tile_size;
boolean b = super.updateResources();
mMaxAllowedRows = getResources().getInteger(R.integer.quick_qs_panel_max_rows);
return b;
}
@Override
+ protected void estimateCellHeight() {
+ FontSizeUtils.updateFontSize(mTempTextView, R.dimen.qs_tile_text_size);
+ int unspecifiedSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ mTempTextView.measure(unspecifiedSpec, unspecifiedSpec);
+ int padding = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_padding);
+ // the QQS only have 1 label
+ mEstimatedCellHeight = mTempTextView.getMeasuredHeight() + padding * 2;
+ }
+
+ @Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateResources();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 269a158..19bf018 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -9,10 +9,12 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.TextView;
import androidx.annotation.Nullable;
import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel.QSTileLayout;
import com.android.systemui.qs.QSPanelControllerBase.TileRecord;
@@ -29,9 +31,10 @@
protected int mColumns;
protected int mCellWidth;
- protected int mCellHeightResId = R.dimen.qs_tile_height;
+ protected int mResourceCellHeightResId = R.dimen.qs_tile_height;
+ protected int mResourceCellHeight;
+ protected int mEstimatedCellHeight;
protected int mCellHeight;
- protected int mMaxCellHeight;
protected int mCellMarginHorizontal;
protected int mCellMarginVertical;
protected int mSidePadding;
@@ -49,6 +52,8 @@
private float mSquishinessFraction = 1f;
protected int mLastTileBottom;
+ protected TextView mTempTextView;
+
public TileLayout(Context context) {
this(context, null);
}
@@ -57,6 +62,7 @@
super(context, attrs);
mLessRows = ((Settings.System.getInt(context.getContentResolver(), "qs_less_rows", 0) != 0)
|| useQsMediaPlayer(context));
+ mTempTextView = new TextView(context);
updateResources();
}
@@ -120,14 +126,19 @@
}
public boolean updateResources() {
- final Resources res = mContext.getResources();
+ Resources res = getResources();
mResourceColumns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
- mMaxCellHeight = mContext.getResources().getDimensionPixelSize(mCellHeightResId);
+ mResourceCellHeight = res.getDimensionPixelSize(mResourceCellHeightResId);
mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
mSidePadding = useSidePadding() ? mCellMarginHorizontal / 2 : 0;
mCellMarginVertical= res.getDimensionPixelSize(R.dimen.qs_tile_margin_vertical);
mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
- if (mLessRows) mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
+ if (mLessRows) {
+ mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
+ }
+ // update estimated cell height under current font scaling
+ mTempTextView.dispatchConfigurationChanged(mContext.getResources().getConfiguration());
+ estimateCellHeight();
if (updateColumns()) {
requestLayout();
return true;
@@ -211,8 +222,23 @@
return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
}
+ // Estimate the height for the tile with 2 labels (general case) under current font scaling.
+ protected void estimateCellHeight() {
+ FontSizeUtils.updateFontSize(mTempTextView, R.dimen.qs_tile_text_size);
+ int unspecifiedSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ mTempTextView.measure(unspecifiedSpec, unspecifiedSpec);
+ int padding = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_padding);
+ mEstimatedCellHeight = mTempTextView.getMeasuredHeight() * 2 + padding * 2;
+ }
+
protected int getCellHeight() {
- return mMaxCellHeight;
+ // Compare estimated height with resource height and return the larger one.
+ // If estimated height > resource height, it means the resource height is not enough
+ // for the tile content under current font scaling. Therefore, we need to use the estimated
+ // height to have a full tile content view.
+ // If estimated height <= resource height, we can use the resource height for tile to keep
+ // the same UI as original behavior.
+ return Math.max(mResourceCellHeight, mEstimatedCellHeight);
}
private void layoutTileRecords(int numRecords, boolean forLayout) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index 35c8cc7..8789253 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -28,8 +28,11 @@
import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableLooper;
+import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.test.runner.AndroidJUnit4;
@@ -48,6 +51,7 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class TileLayoutTest extends SysuiTestCase {
private Resources mResources;
private int mLayoutSizeForOneTile;
@@ -228,4 +232,53 @@
assertEquals(false, mTileLayout.updateResources());
}
+
+ @Test
+ public void fontScalingChanged_updateResources_cellHeightEnoughForTileContent() {
+ final float originalFontScale = mContext.getResources().getConfiguration().fontScale;
+ float[] testScales = {0.8f, 1.0f, 1.4f, 1.6f, 2.0f};
+ for (float scale: testScales) {
+ changeFontScaling_updateResources_cellHeightEnoughForTileContent(scale);
+ }
+
+ changeFontScaling(originalFontScale);
+ }
+
+ private void changeFontScaling_updateResources_cellHeightEnoughForTileContent(float scale) {
+ changeFontScaling(scale);
+
+ QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
+ mTileLayout.addTile(tileRecord);
+
+ FakeTileView tileView = new FakeTileView(mContext);
+ QSTile.State state = new QSTile.State();
+ state.label = "TEST LABEL";
+ state.secondaryLabel = "TEST SECONDARY LABEL";
+ tileView.changeState(state);
+
+ mTileLayout.updateResources();
+
+ int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+ tileView.measure(spec, spec);
+ assertTrue(mTileLayout.getCellHeight() >= tileView.getMeasuredHeight());
+
+ mTileLayout.removeTile(tileRecord);
+ }
+
+ private static class FakeTileView extends QSTileViewImpl {
+ FakeTileView(Context context) {
+ super(context, new QSIconViewImpl(context), /* collapsed= */ false);
+ }
+
+ void changeState(QSTile.State state) {
+ handleStateChanged(state);
+ }
+ }
+
+ private void changeFontScaling(float scale) {
+ Configuration configuration = new Configuration(mContext.getResources().getConfiguration());
+ configuration.fontScale = scale;
+ // updateConfiguration could help update on both resource configuration and displayMetrics
+ mContext.getResources().updateConfiguration(configuration, null, null);
+ }
}