Merge "[View binding] Add ContentDescription as part of the Icon viewmodel." into tm-qpr-dev

This commit is contained in:
Caitlin Shkuratov
2022-09-08 20:37:16 +00:00
committed by Android (Google) Code Review
11 changed files with 57 additions and 36 deletions

View File

@@ -83,7 +83,11 @@ private fun fakeFooterActionsViewModel(
flowOf( flowOf(
securityText?.let { text -> securityText?.let { text ->
SecurityButtonConfig( SecurityButtonConfig(
icon = Icon.Resource(R.drawable.ic_info_outline), icon =
Icon.Resource(
R.drawable.ic_info_outline,
contentDescription = null,
),
text = text, text = text,
isClickable = securityClickable, isClickable = securityClickable,
) )

View File

@@ -24,11 +24,15 @@ import android.graphics.drawable.Drawable
* [Icon.Resource] to a resource. * [Icon.Resource] to a resource.
*/ */
sealed class Icon { sealed class Icon {
abstract val contentDescription: ContentDescription?
data class Loaded( data class Loaded(
val drawable: Drawable, val drawable: Drawable,
override val contentDescription: ContentDescription?,
) : Icon() ) : Icon()
data class Resource( data class Resource(
@DrawableRes val res: Int, @DrawableRes val res: Int,
override val contentDescription: ContentDescription?,
) : Icon() ) : Icon()
} }

View File

@@ -21,14 +21,16 @@ import com.android.systemui.common.shared.model.ContentDescription
object ContentDescriptionViewBinder { object ContentDescriptionViewBinder {
fun bind( fun bind(
contentDescription: ContentDescription, contentDescription: ContentDescription?,
view: View, view: View,
) { ) {
when (contentDescription) { view.contentDescription =
is ContentDescription.Loaded -> view.contentDescription = contentDescription.description when (contentDescription) {
is ContentDescription.Resource -> { null -> null
view.contentDescription = view.context.resources.getString(contentDescription.res) is ContentDescription.Loaded -> contentDescription.description
is ContentDescription.Resource -> {
view.context.resources.getString(contentDescription.res)
}
} }
}
} }
} }

View File

@@ -24,6 +24,7 @@ object IconViewBinder {
icon: Icon, icon: Icon,
view: ImageView, view: ImageView,
) { ) {
ContentDescriptionViewBinder.bind(icon.contentDescription, view)
when (icon) { when (icon) {
is Icon.Loaded -> view.setImageDrawable(icon.drawable) is Icon.Loaded -> view.setImageDrawable(icon.drawable)
is Icon.Resource -> view.setImageResource(icon.res) is Icon.Resource -> view.setImageResource(icon.res)

View File

@@ -97,7 +97,8 @@ public class QSSecurityFooter extends ViewController<View>
super(rootView); super(rootView);
mFooterText = mView.findViewById(R.id.footer_text); mFooterText = mView.findViewById(R.id.footer_text);
mPrimaryFooterIcon = mView.findViewById(R.id.primary_footer_icon); mPrimaryFooterIcon = mView.findViewById(R.id.primary_footer_icon);
mFooterIcon = new Icon.Resource(R.drawable.ic_info_outline); mFooterIcon = new Icon.Resource(
R.drawable.ic_info_outline, /* contentDescription= */ null);
mContext = rootView.getContext(); mContext = rootView.getContext();
mSecurityController = securityController; mSecurityController = securityController;
mMainHandler = mainHandler; mMainHandler = mainHandler;

View File

@@ -75,6 +75,7 @@ import com.android.internal.jank.InteractionJankMonitor;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.animation.DialogCuj; import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.common.shared.model.ContentDescription;
import com.android.systemui.common.shared.model.Icon; import com.android.systemui.common.shared.model.Icon;
import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Application; import com.android.systemui.dagger.qualifiers.Application;
@@ -243,16 +244,17 @@ public class QSSecurityFooterUtils implements DialogInterface.OnClickListener {
isWorkProfileOn).toString(); isWorkProfileOn).toString();
Icon icon; Icon icon;
ContentDescription contentDescription = null;
if (isParentalControlsEnabled) { if (isParentalControlsEnabled) {
icon = new Icon.Loaded(securityModel.getDeviceAdminIcon()); icon = new Icon.Loaded(securityModel.getDeviceAdminIcon(), contentDescription);
} else if (vpnName != null || vpnNameWorkProfile != null) { } else if (vpnName != null || vpnNameWorkProfile != null) {
if (securityModel.isVpnBranded()) { if (securityModel.isVpnBranded()) {
icon = new Icon.Resource(R.drawable.stat_sys_branded_vpn); icon = new Icon.Resource(R.drawable.stat_sys_branded_vpn, contentDescription);
} else { } else {
icon = new Icon.Resource(R.drawable.stat_sys_vpn_ic); icon = new Icon.Resource(R.drawable.stat_sys_vpn_ic, contentDescription);
} }
} else { } else {
icon = new Icon.Resource(R.drawable.ic_info_outline); icon = new Icon.Resource(R.drawable.ic_info_outline, contentDescription);
} }
return new SecurityButtonConfig(icon, text, isClickable); return new SecurityButtonConfig(icon, text, isClickable);

View File

@@ -31,7 +31,6 @@ import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.common.ui.binder.ContentDescriptionViewBinder
import com.android.systemui.common.ui.binder.IconViewBinder import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.people.ui.view.PeopleViewBinder.bind import com.android.systemui.people.ui.view.PeopleViewBinder.bind
@@ -233,10 +232,8 @@ object FooterActionsViewBinder {
val icon = model.icon val icon = model.icon
val iconView = button.icon val iconView = button.icon
val contentDescription = model.contentDescription
IconViewBinder.bind(icon, iconView) IconViewBinder.bind(icon, iconView)
ContentDescriptionViewBinder.bind(contentDescription, iconView)
if (model.iconTint != null) { if (model.iconTint != null) {
iconView.setColorFilter(model.iconTint, PorterDuff.Mode.SRC_IN) iconView.setColorFilter(model.iconTint, PorterDuff.Mode.SRC_IN)
} else { } else {

View File

@@ -18,7 +18,6 @@ package com.android.systemui.qs.footer.ui.viewmodel
import android.annotation.DrawableRes import android.annotation.DrawableRes
import android.view.View import android.view.View
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Icon
/** /**
@@ -29,7 +28,6 @@ data class FooterActionsButtonViewModel(
val icon: Icon, val icon: Icon,
val iconTint: Int?, val iconTint: Int?,
@DrawableRes val background: Int, @DrawableRes val background: Int,
val contentDescription: ContentDescription,
// TODO(b/230830644): Replace View by an Expandable interface that can expand in either dialog // TODO(b/230830644): Replace View by an Expandable interface that can expand in either dialog
// or activity. // or activity.
val onClick: (View) -> Unit, val onClick: (View) -> Unit,

View File

@@ -138,10 +138,12 @@ class FooterActionsViewModel(
/** The model for the settings button. */ /** The model for the settings button. */
val settings: FooterActionsButtonViewModel = val settings: FooterActionsButtonViewModel =
FooterActionsButtonViewModel( FooterActionsButtonViewModel(
Icon.Resource(R.drawable.ic_settings), Icon.Resource(
R.drawable.ic_settings,
ContentDescription.Resource(R.string.accessibility_quick_settings_settings)
),
iconTint = null, iconTint = null,
R.drawable.qs_footer_action_circle, R.drawable.qs_footer_action_circle,
ContentDescription.Resource(R.string.accessibility_quick_settings_settings),
this::onSettingsButtonClicked, this::onSettingsButtonClicked,
) )
@@ -149,14 +151,16 @@ class FooterActionsViewModel(
val power: FooterActionsButtonViewModel? = val power: FooterActionsButtonViewModel? =
if (showPowerButton) { if (showPowerButton) {
FooterActionsButtonViewModel( FooterActionsButtonViewModel(
Icon.Resource(android.R.drawable.ic_lock_power_off), Icon.Resource(
android.R.drawable.ic_lock_power_off,
ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu)
),
iconTint = iconTint =
Utils.getColorAttrDefaultColor( Utils.getColorAttrDefaultColor(
context, context,
com.android.internal.R.attr.textColorOnAccent, com.android.internal.R.attr.textColorOnAccent,
), ),
R.drawable.qs_footer_action_circle_color, R.drawable.qs_footer_action_circle_color,
ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
this::onPowerButtonClicked, this::onPowerButtonClicked,
) )
} else { } else {
@@ -252,10 +256,12 @@ class FooterActionsViewModel(
} }
return FooterActionsButtonViewModel( return FooterActionsButtonViewModel(
Icon.Loaded(icon), Icon.Loaded(
icon,
ContentDescription.Loaded(userSwitcherContentDescription(status.currentUserName)),
),
iconTint, iconTint,
R.drawable.qs_footer_action_circle, R.drawable.qs_footer_action_circle,
ContentDescription.Loaded(userSwitcherContentDescription(status.currentUserName)),
this::onUserSwitcherClicked, this::onUserSwitcherClicked,
) )
} }

View File

@@ -72,7 +72,8 @@ class WifiViewModel @Inject constructor(
isForceHidden || isForceHidden ||
iconResId == null || iconResId == null ||
iconResId <= 0 -> null iconResId <= 0 -> null
else -> Icon.Resource(iconResId) // TODO(b/238425913): Implement the content description.
else -> Icon.Resource(iconResId, /* contentDescription= */ null)
} }
} }

View File

@@ -70,9 +70,13 @@ class FooterActionsViewModelTest : SysuiTestCase() {
val underTest = utils.footerActionsViewModel(showPowerButton = false) val underTest = utils.footerActionsViewModel(showPowerButton = false)
val settings = underTest.settings val settings = underTest.settings
assertThat(settings.contentDescription) assertThat(settings.icon)
.isEqualTo(ContentDescription.Resource(R.string.accessibility_quick_settings_settings)) .isEqualTo(
assertThat(settings.icon).isEqualTo(Icon.Resource(R.drawable.ic_settings)) Icon.Resource(
R.drawable.ic_settings,
ContentDescription.Resource(R.string.accessibility_quick_settings_settings)
)
)
assertThat(settings.background).isEqualTo(R.drawable.qs_footer_action_circle) assertThat(settings.background).isEqualTo(R.drawable.qs_footer_action_circle)
assertThat(settings.iconTint).isNull() assertThat(settings.iconTint).isNull()
} }
@@ -87,11 +91,13 @@ class FooterActionsViewModelTest : SysuiTestCase() {
val underTestWithPower = utils.footerActionsViewModel(showPowerButton = true) val underTestWithPower = utils.footerActionsViewModel(showPowerButton = true)
val power = underTestWithPower.power val power = underTestWithPower.power
assertThat(power).isNotNull() assertThat(power).isNotNull()
assertThat(power!!.contentDescription) assertThat(power!!.icon)
.isEqualTo( .isEqualTo(
ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu) Icon.Resource(
android.R.drawable.ic_lock_power_off,
ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu)
)
) )
assertThat(power.icon).isEqualTo(Icon.Resource(android.R.drawable.ic_lock_power_off))
assertThat(power.background).isEqualTo(R.drawable.qs_footer_action_circle_color) assertThat(power.background).isEqualTo(R.drawable.qs_footer_action_circle_color)
assertThat(power.iconTint) assertThat(power.iconTint)
.isEqualTo( .isEqualTo(
@@ -164,14 +170,13 @@ class FooterActionsViewModelTest : SysuiTestCase() {
utils.setUserSwitcherEnabled(settings, true, userId) utils.setUserSwitcherEnabled(settings, true, userId)
val userSwitcher = currentUserSwitcher() val userSwitcher = currentUserSwitcher()
assertThat(userSwitcher).isNotNull() assertThat(userSwitcher).isNotNull()
assertThat(userSwitcher!!.contentDescription) assertThat(userSwitcher!!.icon)
.isEqualTo(ContentDescription.Loaded("Signed in as foo")) .isEqualTo(Icon.Loaded(picture, ContentDescription.Loaded("Signed in as foo")))
assertThat(userSwitcher.icon).isEqualTo(Icon.Loaded(picture))
assertThat(userSwitcher.background).isEqualTo(R.drawable.qs_footer_action_circle) assertThat(userSwitcher.background).isEqualTo(R.drawable.qs_footer_action_circle)
// Change the current user name. // Change the current user name.
userSwitcherControllerWrapper.currentUserName = "bar" userSwitcherControllerWrapper.currentUserName = "bar"
assertThat(currentUserSwitcher()?.contentDescription) assertThat(currentUserSwitcher()?.icon?.contentDescription)
.isEqualTo(ContentDescription.Loaded("Signed in as bar")) .isEqualTo(ContentDescription.Loaded("Signed in as bar"))
fun iconTint(): Int? = currentUserSwitcher()!!.iconTint fun iconTint(): Int? = currentUserSwitcher()!!.iconTint
@@ -243,7 +248,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
// Map any SecurityModel into a non-null SecurityButtonConfig. // Map any SecurityModel into a non-null SecurityButtonConfig.
val buttonConfig = val buttonConfig =
SecurityButtonConfig( SecurityButtonConfig(
icon = Icon.Resource(0), icon = Icon.Resource(res = 0, contentDescription = null),
text = "foo", text = "foo",
isClickable = true, isClickable = true,
) )
@@ -340,7 +345,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
assertThat(foregroundServices.displayText).isTrue() assertThat(foregroundServices.displayText).isTrue()
securityToConfig = { securityToConfig = {
SecurityButtonConfig( SecurityButtonConfig(
icon = Icon.Resource(0), icon = Icon.Resource(res = 0, contentDescription = null),
text = "foo", text = "foo",
isClickable = true, isClickable = true,
) )