diff options
8 files changed, 74 insertions, 16 deletions
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt new file mode 100644 index 000000000000..e883a4a55af9 --- /dev/null +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/ModifierExt.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.spa.framework.compose + +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics + +/** Sets the content description of this node. */ +fun Modifier.contentDescription(contentDescription: String?) = + if (contentDescription != null) this.semantics { + this.contentDescription = contentDescription + } else this diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt index f5cbe8ffcee3..d08d97eb89db 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt @@ -48,10 +48,9 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import com.android.settingslib.spa.debug.UiModePreviews +import com.android.settingslib.spa.framework.compose.contentDescription import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsShape.CornerExtraLarge import com.android.settingslib.spa.framework.theme.SettingsShape.CornerExtraSmall @@ -191,8 +190,7 @@ private fun Buttons(buttons: List<CardButton>, color: Color) { private fun Button(button: CardButton, color: Color) { TextButton( onClick = button.onClick, - modifier = - Modifier.semantics { button.contentDescription?.let { this.contentDescription = it } } + modifier = Modifier.contentDescription(button.contentDescription), ) { Text(text = button.text, color = color) } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt index 56d75d8bee4b..23a8e78e6c4a 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt @@ -28,6 +28,7 @@ import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -41,7 +42,8 @@ internal fun BaseLayout( title: String, subTitle: @Composable () -> Unit, modifier: Modifier = Modifier, - icon: (@Composable () -> Unit)? = null, + titleContentDescription: String? = null, + icon: @Composable (() -> Unit)? = null, enabled: () -> Boolean = { true }, paddingStart: Dp = SettingsDimension.itemPaddingStart, paddingEnd: Dp = SettingsDimension.itemPaddingEnd, @@ -51,6 +53,7 @@ internal fun BaseLayout( Row( modifier = modifier .fillMaxWidth() + .semantics(mergeDescendants = true) {} .padding(end = paddingEnd), verticalAlignment = Alignment.CenterVertically, ) { @@ -58,6 +61,7 @@ internal fun BaseLayout( BaseIcon(icon, alphaModifier, paddingStart) Titles( title = title, + titleContentDescription = titleContentDescription, subTitle = subTitle, modifier = alphaModifier .weight(1f) @@ -87,9 +91,14 @@ internal fun BaseIcon( // Extracts a scope to avoid frequent recompose outside scope. @Composable -private fun Titles(title: String, subTitle: @Composable () -> Unit, modifier: Modifier) { +private fun Titles( + title: String, + titleContentDescription: String?, + subTitle: @Composable () -> Unit, + modifier: Modifier, +) { Column(modifier) { - SettingsTitle(title) + SettingsTitle(title, titleContentDescription) subTitle() } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt index 194ed81df0ee..e9b3ba2e01f1 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt @@ -32,6 +32,8 @@ internal fun BasePreference( title: String, summary: () -> String, modifier: Modifier = Modifier, + titleContentDescription: String? = null, + summaryContentDescription: () -> String? = { null }, singleLineSummary: Boolean = false, icon: @Composable (() -> Unit)? = null, enabled: () -> Boolean = { true }, @@ -42,9 +44,11 @@ internal fun BasePreference( ) { BaseLayout( title = title, + titleContentDescription = titleContentDescription, subTitle = { SettingsBody( body = summary(), + contentDescription = summaryContentDescription(), maxLines = if (singleLineSummary) 1 else Int.MAX_VALUE, ) }, diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt index 3acf075d8900..4ad4c1496ce8 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt @@ -64,12 +64,24 @@ interface PreferenceModel { val title: String /** + * The content description of [title]. + */ + val titleContentDescription: String? + get() = null + + /** * The summary of this [Preference]. */ val summary: () -> String get() = { "" } /** + * The content description of [summary]. + */ + val summaryContentDescription: () -> String? + get() = { null } + + /** * The icon of this [Preference]. * * Default is `null` which means no icon. @@ -112,7 +124,9 @@ fun Preference( EntryHighlight { BasePreference( title = model.title, + titleContentDescription = model.titleContentDescription, summary = model.summary, + summaryContentDescription = model.summaryContentDescription, singleLineSummary = singleLineSummary, modifier = modifier, icon = model.icon, diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt index 5155406b6d79..2fac576952be 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt @@ -21,8 +21,7 @@ import androidx.compose.material3.Switch import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics +import com.android.settingslib.spa.framework.compose.contentDescription import com.android.settingslib.spa.framework.util.wrapOnSwitchWithLog @Composable @@ -37,9 +36,7 @@ internal fun SettingsSwitch( Switch( checked = checked, onCheckedChange = wrapOnSwitchWithLog(onCheckedChange), - modifier = if (contentDescription != null) Modifier.semantics { - this.contentDescription = contentDescription - } else Modifier, + modifier = Modifier.contentDescription(contentDescription), enabled = changeable(), interactionSource = interactionSource, ) diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt index a59b95a60879..d423d9fe5897 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt @@ -30,16 +30,23 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.android.settingslib.spa.framework.compose.contentDescription import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsOpacity.alphaForEnabled import com.android.settingslib.spa.framework.theme.SettingsTheme import com.android.settingslib.spa.framework.theme.toMediumWeight @Composable -fun SettingsTitle(title: String, useMediumWeight: Boolean = false) { +fun SettingsTitle( + title: String, + contentDescription: String? = null, + useMediumWeight: Boolean = false, +) { Text( text = title, - modifier = Modifier.padding(vertical = SettingsDimension.paddingTiny), + modifier = Modifier + .padding(vertical = SettingsDimension.paddingTiny) + .contentDescription(contentDescription), color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.titleMedium.withWeight(useMediumWeight), ) @@ -81,11 +88,13 @@ fun SettingsListItem(text: String, enabled: Boolean = true) { @Composable fun SettingsBody( body: String, + contentDescription: String? = null, maxLines: Int = Int.MAX_VALUE, ) { if (body.isNotEmpty()) { Text( text = body, + modifier = Modifier.contentDescription(contentDescription), color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyMedium, overflow = TextOverflow.Ellipsis, diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt index 8c363db92e19..5ef3329541f2 100644 --- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt +++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.test.assertHeightIsAtLeast import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performClick import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -93,11 +94,10 @@ class PreferenceTest { } } - val summaryNode = composeTestRule.onNodeWithText(LONG_SUMMARY) try { // There is no assertHeightIsAtMost, so use the assertHeightIsAtLeast and catch the // expected exception. - summaryNode.assertHeightIsAtLeast(lineHeightDp.times(2)) + composeTestRule.onRoot().assertHeightIsAtLeast(lineHeightDp.times(5)) } catch (e: AssertionError) { assertThat(e).hasMessageThat().contains("height") return |