Loading packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePageProvider.kt +21 −0 Original line number Original line Diff line number Diff line Loading @@ -20,11 +20,13 @@ import android.os.Bundle import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.DisabledByDefault import androidx.compose.material.icons.outlined.DisabledByDefault import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable import androidx.compose.runtime.IntState import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview Loading @@ -33,8 +35,11 @@ import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.theme.SettingsTheme import com.android.settingslib.spa.framework.theme.SettingsTheme import com.android.settingslib.spa.gallery.R import com.android.settingslib.spa.gallery.R import com.android.settingslib.spa.widget.preference.ListPreferenceModel import com.android.settingslib.spa.widget.preference.ListPreferenceOption import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.RadioPreferences import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.ui.Category import com.android.settingslib.spa.widget.ui.Category import com.android.settingslib.spa.widget.ui.SettingsIcon import com.android.settingslib.spa.widget.ui.SettingsIcon Loading Loading @@ -103,6 +108,22 @@ object PreferencePageProvider : SettingsPageProvider { override val summary = { ticks.toString() } override val summary = { ticks.toString() } }) }) } } val selectedId = rememberSaveable { mutableIntStateOf(0) } RadioPreferences( object : ListPreferenceModel { override val title: String = "RadioPreferences" override val options: List<ListPreferenceOption> = listOf( ListPreferenceOption(id = 0, text = "option1"), ListPreferenceOption(id = 1, text = "option2"), ListPreferenceOption(id = 2, text = "option3"), ) override val selectedId: IntState = selectedId override val onIdSelected: (Int) -> Unit = { selectedId.intValue = it } } ) } } } } Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/RadioPreferences.kt +54 −16 Original line number Original line Diff line number Diff line Loading @@ -16,28 +16,34 @@ package com.android.settingslib.spa.widget.preference package com.android.settingslib.spa.widget.preference import androidx.compose.foundation.layout.Column import androidx.compose.foundation.background import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable import androidx.compose.runtime.IntState import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role import androidx.compose.ui.tooling.preview.Preview import com.android.settingslib.spa.framework.compose.thenIf import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.widget.ui.CategoryTitle import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled import com.android.settingslib.spa.widget.ui.Category import com.android.settingslib.spa.widget.ui.SettingsListItem import com.android.settingslib.spa.widget.ui.SettingsListItem @Composable @Composable fun RadioPreferences(model: ListPreferenceModel) { fun RadioPreferences(model: ListPreferenceModel) { CategoryTitle(title = model.title) Category(modifier = Modifier.selectableGroup(), title = model.title) { Spacer(modifier = Modifier.width(SettingsDimension.itemDividerHeight)) Column(modifier = Modifier.selectableGroup()) { for (option in model.options) { for (option in model.options) { Radio2(option, model.selectedId.intValue, model.enabled()) { Radio2(option, model.selectedId.intValue, model.enabled()) { model.onIdSelected(it) model.onIdSelected(it) Loading @@ -54,20 +60,52 @@ fun Radio2( onIdSelected: (id: Int) -> Unit, onIdSelected: (id: Int) -> Unit, ) { ) { val selected = option.id == selectedId val selected = option.id == selectedId val surfaceBright = MaterialTheme.colorScheme.surfaceBright Row( Row( modifier = Modifier modifier = .fillMaxWidth() Modifier.fillMaxWidth() .thenIf(isSpaExpressiveEnabled) { Modifier.heightIn(min = SettingsDimension.preferenceMinHeight) .background(surfaceBright) } .selectable( .selectable( selected = selected, selected = selected, enabled = enabled, enabled = enabled, onClick = { onIdSelected(option.id) }, onClick = { onIdSelected(option.id) }, role = Role.RadioButton, role = Role.RadioButton, ) ) .padding(SettingsDimension.dialogItemPadding), .then( if (isSpaExpressiveEnabled) Modifier.padding(SettingsDimension.itemPadding) else Modifier.padding(SettingsDimension.dialogItemPadding) ), verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically, ) { ) { RadioButton(selected = selected, onClick = null, enabled = enabled) RadioButton(selected = selected, onClick = null, enabled = enabled) Spacer(modifier = Modifier.width(SettingsDimension.itemDividerHeight)) Spacer( modifier = Modifier.width( if (isSpaExpressiveEnabled) SettingsDimension.paddingExtraSmall6 else SettingsDimension.itemDividerHeight ) ) SettingsListItem(text = option.text, enabled = enabled) SettingsListItem(text = option.text, enabled = enabled) } } } } @Preview @Composable private fun RadioPreferencePreview() { RadioPreferences( object : ListPreferenceModel { override val title: String = "Title" override val options: List<ListPreferenceOption> = listOf( ListPreferenceOption(id = 0, text = "option1"), ListPreferenceOption(id = 1, text = "option2"), ListPreferenceOption(id = 2, text = "option3"), ) override val selectedId: IntState = remember { mutableIntStateOf(0) } override val onIdSelected: (Int) -> Unit = {} } ) } packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt +3 −3 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,7 @@ fun CategoryTitle(title: String) { * visually separates groups of items. * visually separates groups of items. */ */ @Composable @Composable fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit) { fun Category(title: String? = null, modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) { var displayTitle by remember { mutableStateOf(false) } var displayTitle by remember { mutableStateOf(false) } Column( Column( modifier = modifier = Loading @@ -90,7 +90,7 @@ fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit) if (title != null && displayTitle) CategoryTitle(title = title) if (title != null && displayTitle) CategoryTitle(title = title) Column( Column( modifier = modifier = Modifier.onGloballyPositioned { coordinates -> modifier.onGloballyPositioned { coordinates -> displayTitle = coordinates.size.height > 0 displayTitle = coordinates.size.height > 0 } } .then( .then( Loading Loading @@ -162,7 +162,7 @@ internal val LocalIsInCategory = compositionLocalOf { false } @Composable @Composable private fun CategoryPreview() { private fun CategoryPreview() { SettingsTheme { SettingsTheme { Category("Appearance") { Category(title = "Appearance") { Preference( Preference( object : PreferenceModel { object : PreferenceModel { override val title = "Title" override val title = "Title" Loading packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/RadioPreferencesTest.kt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -43,7 +43,9 @@ class RadioPreferencesTest { RadioPreferences(remember { RadioPreferences(remember { object : ListPreferenceModel { object : ListPreferenceModel { override val title = TITLE override val title = TITLE override val options = emptyList<ListPreferenceOption>() override val options = listOf( ListPreferenceOption(id = 1, text = "A") ) override val selectedId = mutableIntStateOf(0) override val selectedId = mutableIntStateOf(0) override val onIdSelected: (Int) -> Unit = {} override val onIdSelected: (Int) -> Unit = {} } } Loading Loading
packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePageProvider.kt +21 −0 Original line number Original line Diff line number Diff line Loading @@ -20,11 +20,13 @@ import android.os.Bundle import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.DisabledByDefault import androidx.compose.material.icons.outlined.DisabledByDefault import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable import androidx.compose.runtime.IntState import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview Loading @@ -33,8 +35,11 @@ import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.theme.SettingsTheme import com.android.settingslib.spa.framework.theme.SettingsTheme import com.android.settingslib.spa.gallery.R import com.android.settingslib.spa.gallery.R import com.android.settingslib.spa.widget.preference.ListPreferenceModel import com.android.settingslib.spa.widget.preference.ListPreferenceOption import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.RadioPreferences import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.ui.Category import com.android.settingslib.spa.widget.ui.Category import com.android.settingslib.spa.widget.ui.SettingsIcon import com.android.settingslib.spa.widget.ui.SettingsIcon Loading Loading @@ -103,6 +108,22 @@ object PreferencePageProvider : SettingsPageProvider { override val summary = { ticks.toString() } override val summary = { ticks.toString() } }) }) } } val selectedId = rememberSaveable { mutableIntStateOf(0) } RadioPreferences( object : ListPreferenceModel { override val title: String = "RadioPreferences" override val options: List<ListPreferenceOption> = listOf( ListPreferenceOption(id = 0, text = "option1"), ListPreferenceOption(id = 1, text = "option2"), ListPreferenceOption(id = 2, text = "option3"), ) override val selectedId: IntState = selectedId override val onIdSelected: (Int) -> Unit = { selectedId.intValue = it } } ) } } } } Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/RadioPreferences.kt +54 −16 Original line number Original line Diff line number Diff line Loading @@ -16,28 +16,34 @@ package com.android.settingslib.spa.widget.preference package com.android.settingslib.spa.widget.preference import androidx.compose.foundation.layout.Column import androidx.compose.foundation.background import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable import androidx.compose.runtime.IntState import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role import androidx.compose.ui.tooling.preview.Preview import com.android.settingslib.spa.framework.compose.thenIf import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.widget.ui.CategoryTitle import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled import com.android.settingslib.spa.widget.ui.Category import com.android.settingslib.spa.widget.ui.SettingsListItem import com.android.settingslib.spa.widget.ui.SettingsListItem @Composable @Composable fun RadioPreferences(model: ListPreferenceModel) { fun RadioPreferences(model: ListPreferenceModel) { CategoryTitle(title = model.title) Category(modifier = Modifier.selectableGroup(), title = model.title) { Spacer(modifier = Modifier.width(SettingsDimension.itemDividerHeight)) Column(modifier = Modifier.selectableGroup()) { for (option in model.options) { for (option in model.options) { Radio2(option, model.selectedId.intValue, model.enabled()) { Radio2(option, model.selectedId.intValue, model.enabled()) { model.onIdSelected(it) model.onIdSelected(it) Loading @@ -54,20 +60,52 @@ fun Radio2( onIdSelected: (id: Int) -> Unit, onIdSelected: (id: Int) -> Unit, ) { ) { val selected = option.id == selectedId val selected = option.id == selectedId val surfaceBright = MaterialTheme.colorScheme.surfaceBright Row( Row( modifier = Modifier modifier = .fillMaxWidth() Modifier.fillMaxWidth() .thenIf(isSpaExpressiveEnabled) { Modifier.heightIn(min = SettingsDimension.preferenceMinHeight) .background(surfaceBright) } .selectable( .selectable( selected = selected, selected = selected, enabled = enabled, enabled = enabled, onClick = { onIdSelected(option.id) }, onClick = { onIdSelected(option.id) }, role = Role.RadioButton, role = Role.RadioButton, ) ) .padding(SettingsDimension.dialogItemPadding), .then( if (isSpaExpressiveEnabled) Modifier.padding(SettingsDimension.itemPadding) else Modifier.padding(SettingsDimension.dialogItemPadding) ), verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically, ) { ) { RadioButton(selected = selected, onClick = null, enabled = enabled) RadioButton(selected = selected, onClick = null, enabled = enabled) Spacer(modifier = Modifier.width(SettingsDimension.itemDividerHeight)) Spacer( modifier = Modifier.width( if (isSpaExpressiveEnabled) SettingsDimension.paddingExtraSmall6 else SettingsDimension.itemDividerHeight ) ) SettingsListItem(text = option.text, enabled = enabled) SettingsListItem(text = option.text, enabled = enabled) } } } } @Preview @Composable private fun RadioPreferencePreview() { RadioPreferences( object : ListPreferenceModel { override val title: String = "Title" override val options: List<ListPreferenceOption> = listOf( ListPreferenceOption(id = 0, text = "option1"), ListPreferenceOption(id = 1, text = "option2"), ListPreferenceOption(id = 2, text = "option3"), ) override val selectedId: IntState = remember { mutableIntStateOf(0) } override val onIdSelected: (Int) -> Unit = {} } ) }
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt +3 −3 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,7 @@ fun CategoryTitle(title: String) { * visually separates groups of items. * visually separates groups of items. */ */ @Composable @Composable fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit) { fun Category(title: String? = null, modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) { var displayTitle by remember { mutableStateOf(false) } var displayTitle by remember { mutableStateOf(false) } Column( Column( modifier = modifier = Loading @@ -90,7 +90,7 @@ fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit) if (title != null && displayTitle) CategoryTitle(title = title) if (title != null && displayTitle) CategoryTitle(title = title) Column( Column( modifier = modifier = Modifier.onGloballyPositioned { coordinates -> modifier.onGloballyPositioned { coordinates -> displayTitle = coordinates.size.height > 0 displayTitle = coordinates.size.height > 0 } } .then( .then( Loading Loading @@ -162,7 +162,7 @@ internal val LocalIsInCategory = compositionLocalOf { false } @Composable @Composable private fun CategoryPreview() { private fun CategoryPreview() { SettingsTheme { SettingsTheme { Category("Appearance") { Category(title = "Appearance") { Preference( Preference( object : PreferenceModel { object : PreferenceModel { override val title = "Title" override val title = "Title" Loading
packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/RadioPreferencesTest.kt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -43,7 +43,9 @@ class RadioPreferencesTest { RadioPreferences(remember { RadioPreferences(remember { object : ListPreferenceModel { object : ListPreferenceModel { override val title = TITLE override val title = TITLE override val options = emptyList<ListPreferenceOption>() override val options = listOf( ListPreferenceOption(id = 1, text = "A") ) override val selectedId = mutableIntStateOf(0) override val selectedId = mutableIntStateOf(0) override val onIdSelected: (Int) -> Unit = {} override val onIdSelected: (Int) -> Unit = {} } } Loading