Merge "[View binding] Add ContentDescription as part of the Icon viewmodel." into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
001f5e8ca6
@@ -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,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user