diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index 46724adee848a..d8899796b336c 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.view.accessibility.AccessibilityNodeInfo; 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,12 +199,22 @@ public class QuickQSPanel extends QSPanel { @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); diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java index 269a158c6b87c..19bf0188c9d24 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.util.AttributeSet; 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 @@ public class TileLayout extends ViewGroup implements QSTileLayout { 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 @@ public class TileLayout extends ViewGroup implements QSTileLayout { private float mSquishinessFraction = 1f; protected int mLastTileBottom; + protected TextView mTempTextView; + public TileLayout(Context context) { this(context, null); } @@ -57,6 +62,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout { 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 class TileLayout extends ViewGroup implements QSTileLayout { } 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 @@ public class TileLayout extends ViewGroup implements QSTileLayout { 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 35c8cc70953d3..87892539ccfe0 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.times; 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 @@ import org.mockito.Mockito; @SmallTest @RunWith(AndroidJUnit4.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) public class TileLayoutTest extends SysuiTestCase { private Resources mResources; private int mLayoutSizeForOneTile; @@ -228,4 +232,53 @@ public class TileLayoutTest extends SysuiTestCase { 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); + } }