Update Split Shade's status bar font size

When the system's Font Size is changed, the config listener in LargeScreenShadeHeaderController changes the font size of Clock, DateView, and the Carrier Group.

Bug: 222695062
Test: manually, with different font size and display size + atest com.android.systemui.statusbar.phone.LargeScreenShadeHeaderControllerTest
Change-Id: I535a3e3afd7b8539422eb44b90de87a251002195
This commit is contained in:
yyalan
2022-04-01 16:50:06 +01:00
parent 3f28fc9946
commit 957742cf04
6 changed files with 116 additions and 4 deletions

View File

@@ -16,6 +16,8 @@
package com.android.systemui;
import android.annotation.StyleRes;
import android.content.res.TypedArray;
import android.util.TypedValue;
import android.view.View;
import android.widget.TextView;
@@ -23,9 +25,9 @@ import android.widget.TextView;
/**
* Utility class to update the font size when the configuration has changed.
*/
public class FontSizeUtils {
public final class FontSizeUtils {
public static final float LARGE_TEXT_SCALE = 1.3f;
private FontSizeUtils() {}
public static void updateFontSize(View parent, int viewId, int dimensId) {
updateFontSize((TextView) parent.findViewById(viewId), dimensId);
@@ -37,4 +39,20 @@ public class FontSizeUtils {
v.getResources().getDimensionPixelSize(dimensId));
}
}
/**
* Updates the font size according to the style given.
*
* @param v Text to update.
* @param resId Style applying to the text.
*/
public static void updateFontSizeFromStyle(TextView v, @StyleRes int resId) {
int[] attrs = {android.R.attr.textSize};
int indexOfAttrTextSize = 0;
TypedArray ta = v.getContext().obtainStyledAttributes(resId, attrs);
int updatedTextPixelSize = ta.getDimensionPixelSize(indexOfAttrTextSize,
(int) v.getTextSize());
v.setTextSize(TypedValue.COMPLEX_UNIT_PX, updatedTextPixelSize);
ta.recycle();
}
}

View File

@@ -16,6 +16,7 @@
package com.android.systemui.qs.carrier;
import android.annotation.StyleRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.text.TextUtils;
@@ -30,6 +31,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.settingslib.Utils;
import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import java.util.Objects;
@@ -146,4 +148,8 @@ public class QSCarrier extends LinearLayout {
public void setCarrierText(CharSequence text) {
mCarrierText.setText(text);
}
public void updateTextAppearance(@StyleRes int resId) {
FontSizeUtils.updateFontSizeFromStyle(mCarrierText, resId);
}
}

View File

@@ -16,12 +16,14 @@
package com.android.systemui.qs.carrier;
import android.annotation.StyleRes;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
/**
@@ -55,4 +57,11 @@ public class QSCarrierGroup extends LinearLayout {
View getCarrierDivider2() {
return findViewById(R.id.qs_carrier_divider2);
}
public void updateTextAppearance(@StyleRes int resId) {
FontSizeUtils.updateFontSizeFromStyle(getNoSimTextView(), resId);
getCarrier1View().updateTextAppearance(resId);
getCarrier2View().updateTextAppearance(resId);
getCarrier3View().updateTextAppearance(resId);
}
}

View File

@@ -18,9 +18,11 @@ package com.android.systemui.statusbar.phone
import android.app.StatusBarManager
import android.view.View
import android.widget.TextView
import androidx.constraintlayout.motion.widget.MotionLayout
import com.android.settingslib.Utils
import com.android.systemui.Dumpable
import com.android.systemui.FontSizeUtils
import com.android.systemui.R
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
@@ -30,10 +32,12 @@ import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.qs.ChipVisibilityListener
import com.android.systemui.qs.HeaderPrivacyIconsController
import com.android.systemui.qs.carrier.QSCarrierGroup
import com.android.systemui.qs.carrier.QSCarrierGroupController
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_BATTERY_CONTROLLER
import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_SHADE_HEADER
import com.android.systemui.statusbar.policy.ConfigurationController
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Named
@@ -43,6 +47,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
@Named(LARGE_SCREEN_SHADE_HEADER) private val header: View,
private val statusBarIconController: StatusBarIconController,
private val privacyIconsController: HeaderPrivacyIconsController,
private val configurationController: ConfigurationController,
qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
featureFlags: FeatureFlags,
@Named(LARGE_SCREEN_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController,
@@ -69,6 +74,9 @@ class LargeScreenShadeHeaderController @Inject constructor(
private val iconContainer: StatusIconContainer
private val carrierIconSlots: List<String>
private val qsCarrierGroupController: QSCarrierGroupController
private val clock: TextView = header.findViewById(R.id.clock)
private val date: TextView = header.findViewById(R.id.date)
private val qsCarrierGroup: QSCarrierGroup = header.findViewById(R.id.carrier_group)
private var qsDisabled = false
@@ -148,9 +156,9 @@ class LargeScreenShadeHeaderController @Inject constructor(
.load(context, resources.getXml(R.xml.large_screen_shade_header))
privacyIconsController.chipVisibilityListener = chipVisibilityListener
}
}
init {
bindConfigurationListener()
batteryMeterViewController.init()
val batteryIcon: BatteryMeterView = header.findViewById(R.id.batteryRemainingIcon)
@@ -194,6 +202,18 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
private fun bindConfigurationListener() {
val listener = object : ConfigurationController.ConfigurationListener {
override fun onDensityOrFontScaleChanged() {
val qsStatusStyle = R.style.TextAppearance_QS_Status
FontSizeUtils.updateFontSizeFromStyle(clock, qsStatusStyle)
FontSizeUtils.updateFontSizeFromStyle(date, qsStatusStyle)
qsCarrierGroup.updateTextAppearance(qsStatusStyle)
}
}
configurationController.addCallback(listener)
}
private fun onShadeExpandedChanged() {
if (shadeExpanded) {
privacyIconsController.startListening()

View File

@@ -1,8 +1,12 @@
package com.android.systemui.statusbar.phone
import android.app.StatusBarManager
import android.content.Context
import android.content.res.TypedArray
import android.testing.AndroidTestingRunner
import android.util.TypedValue.COMPLEX_UNIT_PX
import android.view.View
import android.widget.TextView
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
@@ -13,7 +17,9 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.qs.HeaderPrivacyIconsController
import com.android.systemui.qs.carrier.QSCarrierGroup
import com.android.systemui.qs.carrier.QSCarrierGroupController
import com.android.systemui.statusbar.policy.FakeConfigurationController
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
@@ -22,6 +28,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
@@ -36,19 +43,32 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
@Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController
@Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
@Mock private lateinit var featureFlags: FeatureFlags
@Mock private lateinit var clock: TextView
@Mock private lateinit var date: TextView
@Mock private lateinit var carrierGroup: QSCarrierGroup
@Mock private lateinit var batteryMeterView: BatteryMeterView
@Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
@Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var mockedContext: Context
@Mock private lateinit var typedArray: TypedArray
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
var viewVisibility = View.GONE
private lateinit var mLargeScreenShadeHeaderController: LargeScreenShadeHeaderController
private lateinit var carrierIconSlots: List<String>
private val configurationController = FakeConfigurationController()
@Before
fun setup() {
whenever<TextView>(view.findViewById(R.id.clock)).thenReturn(clock)
whenever(clock.context).thenReturn(mockedContext)
whenever(mockedContext.obtainStyledAttributes(anyInt(), any())).thenReturn(typedArray)
whenever<TextView>(view.findViewById(R.id.date)).thenReturn(date)
whenever(date.context).thenReturn(mockedContext)
whenever<QSCarrierGroup>(view.findViewById(R.id.carrier_group)).thenReturn(carrierGroup)
whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
.thenReturn(batteryMeterView)
whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
@@ -67,6 +87,7 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
view,
statusBarIconController,
privacyIconsController,
configurationController,
qsCarrierGroupControllerBuilder,
featureFlags,
batteryMeterViewController,
@@ -138,4 +159,38 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
mLargeScreenShadeHeaderController.active = true
mLargeScreenShadeHeaderController.shadeExpanded = true
}
@Test
fun updateConfig_changesFontSize() {
val updatedTextPixelSize = 32
setReturnTextSize(updatedTextPixelSize)
configurationController.notifyDensityOrFontScaleChanged()
verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize.toFloat())
verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize.toFloat())
verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status)
}
@Test
fun updateConfig_changesFontSizeMultipleTimes() {
val updatedTextPixelSize1 = 32
setReturnTextSize(updatedTextPixelSize1)
configurationController.notifyDensityOrFontScaleChanged()
verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize1.toFloat())
verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize1.toFloat())
verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status)
clearInvocations(carrierGroup)
val updatedTextPixelSize2 = 42
setReturnTextSize(updatedTextPixelSize2)
configurationController.notifyDensityOrFontScaleChanged()
verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize2.toFloat())
verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize2.toFloat())
verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status)
}
private fun setReturnTextSize(resultTextSize: Int) {
whenever(typedArray.getDimensionPixelSize(anyInt(), anyInt())).thenReturn(resultTextSize)
}
}

View File

@@ -23,6 +23,10 @@ class FakeConfigurationController : ConfigurationController {
listeners.forEach { it.onThemeChanged() }
}
fun notifyDensityOrFontScaleChanged() {
listeners.forEach { it.onDensityOrFontScaleChanged() }
}
fun notifyConfigurationChanged() {
onConfigurationChanged(newConfiguration = null)
}