Loading packages/SystemUI/res/values/strings.xml +14 −0 Original line number Original line Diff line number Diff line Loading @@ -2698,6 +2698,20 @@ <item quantity="other"><xliff:g id="number" example="3">%s</xliff:g> controls added.</item> <item quantity="other"><xliff:g id="number" example="3">%s</xliff:g> controls added.</item> </plurals> </plurals> <!-- Removed control in management screen [CHAR LIMIT=20] --> <string name="controls_removed">Removed</string> <!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] --> <string name="accessibility_control_favorite">Favorited</string> <!-- a11y state description for a control that is currently favorited with its position [CHAR LIMIT=NONE] --> <string name="accessibility_control_favorite_position">Favorited, position <xliff:g id="number" example="1">%d</xliff:g></string> <!-- a11y state description for a control that is currently not favorited [CHAR LIMIT=NONE] --> <string name="accessibility_control_not_favorite">Unfavorited</string> <!-- a11y action to favorite a control. It will read as "Double-tap to favorite" in screen readers [CHAR LIMIT=NONE] --> <string name="accessibility_control_change_favorite">favorite</string> <!-- a11y action to unfavorite a control. It will read as "Double-tap to unfavorite" in screen readers [CHAR LIMIT=NONE] --> <string name="accessibility_control_change_unfavorite">unfavorite</string> <!-- Controls management controls screen default title [CHAR LIMIT=30] --> <!-- Controls management controls screen default title [CHAR LIMIT=30] --> <string name="controls_favorite_default_title">Controls</string> <string name="controls_favorite_default_title">Controls</string> <!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] --> <!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] --> Loading packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +71 −4 Original line number Original line Diff line number Diff line Loading @@ -23,9 +23,14 @@ import android.service.controls.DeviceTypes import android.view.LayoutInflater import android.view.LayoutInflater import android.view.View import android.view.View import android.view.ViewGroup import android.view.ViewGroup import android.view.accessibility.AccessibilityNodeInfo import android.widget.CheckBox import android.widget.CheckBox import android.widget.ImageView import android.widget.ImageView import android.widget.Switch import android.widget.TextView import android.widget.TextView import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.ViewCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView import com.android.systemui.R import com.android.systemui.R Loading Loading @@ -72,7 +77,8 @@ class ControlAdapter( elevation = this@ControlAdapter.elevation elevation = this@ControlAdapter.elevation background = parent.context.getDrawable( background = parent.context.getDrawable( R.drawable.control_background_ripple) R.drawable.control_background_ripple) } }, model is FavoritesModel // Indicates that position information is needed ) { id, favorite -> ) { id, favorite -> model?.changeFavoriteStatus(id, favorite) model?.changeFavoriteStatus(id, favorite) } } Loading Loading @@ -175,8 +181,14 @@ private class ZoneHolder(view: View) : Holder(view) { */ */ internal class ControlHolder( internal class ControlHolder( view: View, view: View, val withPosition: Boolean, val favoriteCallback: ModelFavoriteChanger val favoriteCallback: ModelFavoriteChanger ) : Holder(view) { ) : Holder(view) { private val favoriteStateDescription = itemView.context.getString(R.string.accessibility_control_favorite) private val notFavoriteStateDescription = itemView.context.getString(R.string.accessibility_control_not_favorite) private val icon: ImageView = itemView.requireViewById(R.id.icon) private val icon: ImageView = itemView.requireViewById(R.id.icon) private val title: TextView = itemView.requireViewById(R.id.title) private val title: TextView = itemView.requireViewById(R.id.title) private val subtitle: TextView = itemView.requireViewById(R.id.subtitle) private val subtitle: TextView = itemView.requireViewById(R.id.subtitle) Loading @@ -185,15 +197,38 @@ internal class ControlHolder( visibility = View.VISIBLE visibility = View.VISIBLE } } private val accessibilityDelegate = ControlHolderAccessibilityDelegate(this::stateDescription) init { ViewCompat.setAccessibilityDelegate(itemView, accessibilityDelegate) } // Determine the stateDescription based on favorite state and maybe position private fun stateDescription(favorite: Boolean): CharSequence? { if (!favorite) { return notFavoriteStateDescription } else if (!withPosition) { return favoriteStateDescription } else { val position = layoutPosition + 1 return itemView.context.getString( R.string.accessibility_control_favorite_position, position) } } override fun bindData(wrapper: ElementWrapper) { override fun bindData(wrapper: ElementWrapper) { wrapper as ControlInterface wrapper as ControlInterface val renderInfo = getRenderInfo(wrapper.component, wrapper.deviceType) val renderInfo = getRenderInfo(wrapper.component, wrapper.deviceType) title.text = wrapper.title title.text = wrapper.title subtitle.text = wrapper.subtitle subtitle.text = wrapper.subtitle favorite.isChecked = wrapper.favorite updateFavorite(wrapper.favorite) removed.text = if (wrapper.removed) "Removed" else "" removed.text = if (wrapper.removed) { itemView.context.getText(R.string.controls_removed) } else { "" } itemView.setOnClickListener { itemView.setOnClickListener { favorite.isChecked = !favorite.isChecked updateFavorite(!favorite.isChecked) favoriteCallback(wrapper.controlId, favorite.isChecked) favoriteCallback(wrapper.controlId, favorite.isChecked) } } applyRenderInfo(renderInfo) applyRenderInfo(renderInfo) Loading @@ -201,6 +236,8 @@ internal class ControlHolder( override fun updateFavorite(favorite: Boolean) { override fun updateFavorite(favorite: Boolean) { this.favorite.isChecked = favorite this.favorite.isChecked = favorite accessibilityDelegate.isFavorite = favorite itemView.stateDescription = stateDescription(favorite) } } private fun getRenderInfo( private fun getRenderInfo( Loading @@ -219,6 +256,36 @@ internal class ControlHolder( } } } } private class ControlHolderAccessibilityDelegate( val stateRetriever: (Boolean) -> CharSequence? ) : AccessibilityDelegateCompat() { var isFavorite = false override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) { super.onInitializeAccessibilityNodeInfo(host, info) // Change the text for the double-tap action val clickActionString = if (isFavorite) { host.context.getString(R.string.accessibility_control_change_unfavorite) } else { host.context.getString(R.string.accessibility_control_change_favorite) } val click = AccessibilityNodeInfoCompat.AccessibilityActionCompat( AccessibilityNodeInfo.ACTION_CLICK, // “favorite/unfavorite” clickActionString) info.addAction(click) // Determine the stateDescription based on the holder information info.stateDescription = stateRetriever(isFavorite) // Remove the information at the end indicating row and column. info.setCollectionItemInfo(null) info.className = Switch::class.java.name } } class MarginItemDecorator( class MarginItemDecorator( private val topMargin: Int, private val topMargin: Int, private val sideMargins: Int private val sideMargins: Int Loading packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt +12 −1 Original line number Original line Diff line number Diff line Loading @@ -191,7 +191,18 @@ class ControlsEditingActivity @Inject constructor( recyclerView.apply { recyclerView.apply { this.adapter = adapter this.adapter = adapter layoutManager = GridLayoutManager(recyclerView.context, 2).apply { layoutManager = object : GridLayoutManager(recyclerView.context, 2) { // This will remove from the announcement the row corresponding to the divider, // as it's not something that should be announced. override fun getRowCountForAccessibility( recycler: RecyclerView.Recycler, state: RecyclerView.State ): Int { val initial = super.getRowCountForAccessibility(recycler, state) return if (initial > 0) initial - 1 else initial } }.apply { spanSizeLookup = adapter.spanSizeLookup spanSizeLookup = adapter.spanSizeLookup } } addItemDecoration(itemDecorator) addItemDecoration(itemDecorator) Loading Loading
packages/SystemUI/res/values/strings.xml +14 −0 Original line number Original line Diff line number Diff line Loading @@ -2698,6 +2698,20 @@ <item quantity="other"><xliff:g id="number" example="3">%s</xliff:g> controls added.</item> <item quantity="other"><xliff:g id="number" example="3">%s</xliff:g> controls added.</item> </plurals> </plurals> <!-- Removed control in management screen [CHAR LIMIT=20] --> <string name="controls_removed">Removed</string> <!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] --> <string name="accessibility_control_favorite">Favorited</string> <!-- a11y state description for a control that is currently favorited with its position [CHAR LIMIT=NONE] --> <string name="accessibility_control_favorite_position">Favorited, position <xliff:g id="number" example="1">%d</xliff:g></string> <!-- a11y state description for a control that is currently not favorited [CHAR LIMIT=NONE] --> <string name="accessibility_control_not_favorite">Unfavorited</string> <!-- a11y action to favorite a control. It will read as "Double-tap to favorite" in screen readers [CHAR LIMIT=NONE] --> <string name="accessibility_control_change_favorite">favorite</string> <!-- a11y action to unfavorite a control. It will read as "Double-tap to unfavorite" in screen readers [CHAR LIMIT=NONE] --> <string name="accessibility_control_change_unfavorite">unfavorite</string> <!-- Controls management controls screen default title [CHAR LIMIT=30] --> <!-- Controls management controls screen default title [CHAR LIMIT=30] --> <string name="controls_favorite_default_title">Controls</string> <string name="controls_favorite_default_title">Controls</string> <!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] --> <!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] --> Loading
packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +71 −4 Original line number Original line Diff line number Diff line Loading @@ -23,9 +23,14 @@ import android.service.controls.DeviceTypes import android.view.LayoutInflater import android.view.LayoutInflater import android.view.View import android.view.View import android.view.ViewGroup import android.view.ViewGroup import android.view.accessibility.AccessibilityNodeInfo import android.widget.CheckBox import android.widget.CheckBox import android.widget.ImageView import android.widget.ImageView import android.widget.Switch import android.widget.TextView import android.widget.TextView import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.ViewCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView import com.android.systemui.R import com.android.systemui.R Loading Loading @@ -72,7 +77,8 @@ class ControlAdapter( elevation = this@ControlAdapter.elevation elevation = this@ControlAdapter.elevation background = parent.context.getDrawable( background = parent.context.getDrawable( R.drawable.control_background_ripple) R.drawable.control_background_ripple) } }, model is FavoritesModel // Indicates that position information is needed ) { id, favorite -> ) { id, favorite -> model?.changeFavoriteStatus(id, favorite) model?.changeFavoriteStatus(id, favorite) } } Loading Loading @@ -175,8 +181,14 @@ private class ZoneHolder(view: View) : Holder(view) { */ */ internal class ControlHolder( internal class ControlHolder( view: View, view: View, val withPosition: Boolean, val favoriteCallback: ModelFavoriteChanger val favoriteCallback: ModelFavoriteChanger ) : Holder(view) { ) : Holder(view) { private val favoriteStateDescription = itemView.context.getString(R.string.accessibility_control_favorite) private val notFavoriteStateDescription = itemView.context.getString(R.string.accessibility_control_not_favorite) private val icon: ImageView = itemView.requireViewById(R.id.icon) private val icon: ImageView = itemView.requireViewById(R.id.icon) private val title: TextView = itemView.requireViewById(R.id.title) private val title: TextView = itemView.requireViewById(R.id.title) private val subtitle: TextView = itemView.requireViewById(R.id.subtitle) private val subtitle: TextView = itemView.requireViewById(R.id.subtitle) Loading @@ -185,15 +197,38 @@ internal class ControlHolder( visibility = View.VISIBLE visibility = View.VISIBLE } } private val accessibilityDelegate = ControlHolderAccessibilityDelegate(this::stateDescription) init { ViewCompat.setAccessibilityDelegate(itemView, accessibilityDelegate) } // Determine the stateDescription based on favorite state and maybe position private fun stateDescription(favorite: Boolean): CharSequence? { if (!favorite) { return notFavoriteStateDescription } else if (!withPosition) { return favoriteStateDescription } else { val position = layoutPosition + 1 return itemView.context.getString( R.string.accessibility_control_favorite_position, position) } } override fun bindData(wrapper: ElementWrapper) { override fun bindData(wrapper: ElementWrapper) { wrapper as ControlInterface wrapper as ControlInterface val renderInfo = getRenderInfo(wrapper.component, wrapper.deviceType) val renderInfo = getRenderInfo(wrapper.component, wrapper.deviceType) title.text = wrapper.title title.text = wrapper.title subtitle.text = wrapper.subtitle subtitle.text = wrapper.subtitle favorite.isChecked = wrapper.favorite updateFavorite(wrapper.favorite) removed.text = if (wrapper.removed) "Removed" else "" removed.text = if (wrapper.removed) { itemView.context.getText(R.string.controls_removed) } else { "" } itemView.setOnClickListener { itemView.setOnClickListener { favorite.isChecked = !favorite.isChecked updateFavorite(!favorite.isChecked) favoriteCallback(wrapper.controlId, favorite.isChecked) favoriteCallback(wrapper.controlId, favorite.isChecked) } } applyRenderInfo(renderInfo) applyRenderInfo(renderInfo) Loading @@ -201,6 +236,8 @@ internal class ControlHolder( override fun updateFavorite(favorite: Boolean) { override fun updateFavorite(favorite: Boolean) { this.favorite.isChecked = favorite this.favorite.isChecked = favorite accessibilityDelegate.isFavorite = favorite itemView.stateDescription = stateDescription(favorite) } } private fun getRenderInfo( private fun getRenderInfo( Loading @@ -219,6 +256,36 @@ internal class ControlHolder( } } } } private class ControlHolderAccessibilityDelegate( val stateRetriever: (Boolean) -> CharSequence? ) : AccessibilityDelegateCompat() { var isFavorite = false override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) { super.onInitializeAccessibilityNodeInfo(host, info) // Change the text for the double-tap action val clickActionString = if (isFavorite) { host.context.getString(R.string.accessibility_control_change_unfavorite) } else { host.context.getString(R.string.accessibility_control_change_favorite) } val click = AccessibilityNodeInfoCompat.AccessibilityActionCompat( AccessibilityNodeInfo.ACTION_CLICK, // “favorite/unfavorite” clickActionString) info.addAction(click) // Determine the stateDescription based on the holder information info.stateDescription = stateRetriever(isFavorite) // Remove the information at the end indicating row and column. info.setCollectionItemInfo(null) info.className = Switch::class.java.name } } class MarginItemDecorator( class MarginItemDecorator( private val topMargin: Int, private val topMargin: Int, private val sideMargins: Int private val sideMargins: Int Loading
packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt +12 −1 Original line number Original line Diff line number Diff line Loading @@ -191,7 +191,18 @@ class ControlsEditingActivity @Inject constructor( recyclerView.apply { recyclerView.apply { this.adapter = adapter this.adapter = adapter layoutManager = GridLayoutManager(recyclerView.context, 2).apply { layoutManager = object : GridLayoutManager(recyclerView.context, 2) { // This will remove from the announcement the row corresponding to the divider, // as it's not something that should be announced. override fun getRowCountForAccessibility( recycler: RecyclerView.Recycler, state: RecyclerView.State ): Int { val initial = super.getRowCountForAccessibility(recycler, state) return if (initial > 0) initial - 1 else initial } }.apply { spanSizeLookup = adapter.spanSizeLookup spanSizeLookup = adapter.spanSizeLookup } } addItemDecoration(itemDecorator) addItemDecoration(itemDecorator) Loading