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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user