Loading packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt +9 −6 Original line number Diff line number Diff line Loading @@ -19,9 +19,11 @@ package com.android.settingslib.spa.gallery.ui import android.os.Bundle import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.tooling.preview.Preview import com.android.settingslib.spa.framework.common.SettingsEntryBuilder import com.android.settingslib.spa.framework.common.SettingsPage Loading @@ -32,6 +34,7 @@ import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.ui.Spinner import com.android.settingslib.spa.widget.ui.SpinnerOption private const val TITLE = "Sample Spinner" Loading @@ -55,16 +58,16 @@ object SpinnerPageProvider : SettingsPageProvider { @Composable override fun Page(arguments: Bundle?) { RegularScaffold(title = getTitle(arguments)) { val selectedIndex = rememberSaveable { mutableStateOf(0) } var selectedId by rememberSaveable { mutableStateOf(1) } Spinner( options = (1..3).map { "Option $it" }, selectedIndex = selectedIndex.value, setIndex = { selectedIndex.value = it }, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = selectedId, setId = { selectedId = it }, ) Preference(object : PreferenceModel { override val title = "Selected index" override val title = "Selected id" override val summary = remember { derivedStateOf { selectedIndex.value.toString() } derivedStateOf { selectedId.toString() } } }) } Loading packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/SpinnerScreenshotTest.kt +4 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.settingslib.spa.screenshot import com.android.settingslib.spa.widget.ui.Spinner import com.android.settingslib.spa.widget.ui.SpinnerOption import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith Loading @@ -43,9 +44,9 @@ class SpinnerScreenshotTest(emulationSpec: DeviceEmulationSpec) { fun test() { screenshotRule.screenshotTest("spinner") { Spinner( options = (1..3).map { "Option $it" }, selectedIndex = 0, setIndex = {}, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = 1, setId = {}, ) } } Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt +16 −11 Original line number Diff line number Diff line Loading @@ -45,8 +45,13 @@ import androidx.compose.ui.unit.dp import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsTheme data class SpinnerOption( val id: Int, val text: String, ) @Composable fun Spinner(options: List<String>, selectedIndex: Int, setIndex: (index: Int) -> Unit) { fun Spinner(options: List<SpinnerOption>, selectedId: Int?, setId: (id: Int) -> Unit) { if (options.isEmpty()) { return } Loading @@ -68,7 +73,7 @@ fun Spinner(options: List<String>, selectedIndex: Int, setIndex: (index: Int) -> ), contentPadding = contentPadding, ) { SpinnerText(options[selectedIndex]) SpinnerText(options.find { it.id == selectedId }) Icon( imageVector = when { expanded -> Icons.Outlined.ArrowDropUp Loading @@ -83,18 +88,18 @@ fun Spinner(options: List<String>, selectedIndex: Int, setIndex: (index: Int) -> modifier = Modifier.background(SettingsTheme.colorScheme.spinnerItemContainer), offset = DpOffset(x = 0.dp, y = 4.dp), ) { options.forEachIndexed { index, option -> for (option in options) { DropdownMenuItem( text = { SpinnerText( text = option, option = option, modifier = Modifier.padding(end = 24.dp), color = SettingsTheme.colorScheme.onSpinnerItemContainer, ) }, onClick = { expanded = false setIndex(index) setId(option.id) }, contentPadding = contentPadding, ) Loading @@ -105,12 +110,12 @@ fun Spinner(options: List<String>, selectedIndex: Int, setIndex: (index: Int) -> @Composable private fun SpinnerText( text: String, option: SpinnerOption?, modifier: Modifier = Modifier, color: Color = Color.Unspecified, ) { Text( text = text, text = option?.text ?: "", modifier = modifier.padding(end = SettingsDimension.itemPaddingEnd), color = color, style = MaterialTheme.typography.labelLarge, Loading @@ -121,11 +126,11 @@ private fun SpinnerText( @Composable private fun SpinnerPreview() { SettingsTheme { var selectedIndex by rememberSaveable { mutableStateOf(0) } var selectedId by rememberSaveable { mutableStateOf(1) } Spinner( options = (1..3).map { "Option $it" }, selectedIndex = selectedIndex, setIndex = { selectedIndex = it }, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = selectedId, setId = { selectedId = it }, ) } } packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/SpinnerTest.kt +10 −10 Original line number Diff line number Diff line Loading @@ -36,28 +36,28 @@ class SpinnerTest { @Test fun spinner_initialState() { var selectedIndex by mutableStateOf(0) var selectedId by mutableStateOf(1) composeTestRule.setContent { Spinner( options = (1..3).map { "Option $it" }, selectedIndex = selectedIndex, setIndex = { selectedIndex = it }, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = selectedId, setId = { selectedId = it }, ) } composeTestRule.onNodeWithText("Option 1").assertIsDisplayed() composeTestRule.onNodeWithText("Option 2").assertDoesNotExist() assertThat(selectedIndex).isEqualTo(0) assertThat(selectedId).isEqualTo(1) } @Test fun spinner_canChangeState() { var selectedIndex by mutableStateOf(0) var selectedId by mutableStateOf(1) composeTestRule.setContent { Spinner( options = (1..3).map { "Option $it" }, selectedIndex = selectedIndex, setIndex = { selectedIndex = it }, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = selectedId, setId = { selectedId = it }, ) } Loading @@ -66,6 +66,6 @@ class SpinnerTest { composeTestRule.onNodeWithText("Option 1").assertDoesNotExist() composeTestRule.onNodeWithText("Option 2").assertIsDisplayed() assertThat(selectedIndex).isEqualTo(1) assertThat(selectedId).isEqualTo(2) } } packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt +5 −2 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import android.content.pm.ApplicationInfo import android.icu.text.CollationKey import androidx.compose.runtime.Composable import androidx.compose.runtime.State import com.android.settingslib.spa.widget.ui.SpinnerOption import com.android.settingslib.spaprivileged.template.app.AppListItem import com.android.settingslib.spaprivileged.template.app.AppListItemModel import kotlinx.coroutines.flow.Flow Loading @@ -23,7 +24,7 @@ interface AppListModel<T : AppRecord> { * * Default no spinner will be shown. */ fun getSpinnerOptions(): List<String> = emptyList() fun getSpinnerOptions(recordList: List<T>): List<SpinnerOption> = emptyList() /** * Loads the extra info for the App List, and generates the [AppRecord] List. Loading @@ -42,8 +43,10 @@ interface AppListModel<T : AppRecord> { * This function is called when the App List's loading is finished and displayed to the user. * * Could do some pre-cache here. * * @return true to enable pre-fetching app labels. */ suspend fun onFirstLoaded(recordList: List<T>) {} suspend fun onFirstLoaded(recordList: List<T>) = false /** * Gets the comparator to sort the App List. Loading Loading
packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt +9 −6 Original line number Diff line number Diff line Loading @@ -19,9 +19,11 @@ package com.android.settingslib.spa.gallery.ui import android.os.Bundle import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.tooling.preview.Preview import com.android.settingslib.spa.framework.common.SettingsEntryBuilder import com.android.settingslib.spa.framework.common.SettingsPage Loading @@ -32,6 +34,7 @@ import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.ui.Spinner import com.android.settingslib.spa.widget.ui.SpinnerOption private const val TITLE = "Sample Spinner" Loading @@ -55,16 +58,16 @@ object SpinnerPageProvider : SettingsPageProvider { @Composable override fun Page(arguments: Bundle?) { RegularScaffold(title = getTitle(arguments)) { val selectedIndex = rememberSaveable { mutableStateOf(0) } var selectedId by rememberSaveable { mutableStateOf(1) } Spinner( options = (1..3).map { "Option $it" }, selectedIndex = selectedIndex.value, setIndex = { selectedIndex.value = it }, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = selectedId, setId = { selectedId = it }, ) Preference(object : PreferenceModel { override val title = "Selected index" override val title = "Selected id" override val summary = remember { derivedStateOf { selectedIndex.value.toString() } derivedStateOf { selectedId.toString() } } }) } Loading
packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/SpinnerScreenshotTest.kt +4 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.settingslib.spa.screenshot import com.android.settingslib.spa.widget.ui.Spinner import com.android.settingslib.spa.widget.ui.SpinnerOption import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith Loading @@ -43,9 +44,9 @@ class SpinnerScreenshotTest(emulationSpec: DeviceEmulationSpec) { fun test() { screenshotRule.screenshotTest("spinner") { Spinner( options = (1..3).map { "Option $it" }, selectedIndex = 0, setIndex = {}, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = 1, setId = {}, ) } } Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt +16 −11 Original line number Diff line number Diff line Loading @@ -45,8 +45,13 @@ import androidx.compose.ui.unit.dp import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsTheme data class SpinnerOption( val id: Int, val text: String, ) @Composable fun Spinner(options: List<String>, selectedIndex: Int, setIndex: (index: Int) -> Unit) { fun Spinner(options: List<SpinnerOption>, selectedId: Int?, setId: (id: Int) -> Unit) { if (options.isEmpty()) { return } Loading @@ -68,7 +73,7 @@ fun Spinner(options: List<String>, selectedIndex: Int, setIndex: (index: Int) -> ), contentPadding = contentPadding, ) { SpinnerText(options[selectedIndex]) SpinnerText(options.find { it.id == selectedId }) Icon( imageVector = when { expanded -> Icons.Outlined.ArrowDropUp Loading @@ -83,18 +88,18 @@ fun Spinner(options: List<String>, selectedIndex: Int, setIndex: (index: Int) -> modifier = Modifier.background(SettingsTheme.colorScheme.spinnerItemContainer), offset = DpOffset(x = 0.dp, y = 4.dp), ) { options.forEachIndexed { index, option -> for (option in options) { DropdownMenuItem( text = { SpinnerText( text = option, option = option, modifier = Modifier.padding(end = 24.dp), color = SettingsTheme.colorScheme.onSpinnerItemContainer, ) }, onClick = { expanded = false setIndex(index) setId(option.id) }, contentPadding = contentPadding, ) Loading @@ -105,12 +110,12 @@ fun Spinner(options: List<String>, selectedIndex: Int, setIndex: (index: Int) -> @Composable private fun SpinnerText( text: String, option: SpinnerOption?, modifier: Modifier = Modifier, color: Color = Color.Unspecified, ) { Text( text = text, text = option?.text ?: "", modifier = modifier.padding(end = SettingsDimension.itemPaddingEnd), color = color, style = MaterialTheme.typography.labelLarge, Loading @@ -121,11 +126,11 @@ private fun SpinnerText( @Composable private fun SpinnerPreview() { SettingsTheme { var selectedIndex by rememberSaveable { mutableStateOf(0) } var selectedId by rememberSaveable { mutableStateOf(1) } Spinner( options = (1..3).map { "Option $it" }, selectedIndex = selectedIndex, setIndex = { selectedIndex = it }, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = selectedId, setId = { selectedId = it }, ) } }
packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/SpinnerTest.kt +10 −10 Original line number Diff line number Diff line Loading @@ -36,28 +36,28 @@ class SpinnerTest { @Test fun spinner_initialState() { var selectedIndex by mutableStateOf(0) var selectedId by mutableStateOf(1) composeTestRule.setContent { Spinner( options = (1..3).map { "Option $it" }, selectedIndex = selectedIndex, setIndex = { selectedIndex = it }, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = selectedId, setId = { selectedId = it }, ) } composeTestRule.onNodeWithText("Option 1").assertIsDisplayed() composeTestRule.onNodeWithText("Option 2").assertDoesNotExist() assertThat(selectedIndex).isEqualTo(0) assertThat(selectedId).isEqualTo(1) } @Test fun spinner_canChangeState() { var selectedIndex by mutableStateOf(0) var selectedId by mutableStateOf(1) composeTestRule.setContent { Spinner( options = (1..3).map { "Option $it" }, selectedIndex = selectedIndex, setIndex = { selectedIndex = it }, options = (1..3).map { SpinnerOption(id = it, text = "Option $it") }, selectedId = selectedId, setId = { selectedId = it }, ) } Loading @@ -66,6 +66,6 @@ class SpinnerTest { composeTestRule.onNodeWithText("Option 1").assertDoesNotExist() composeTestRule.onNodeWithText("Option 2").assertIsDisplayed() assertThat(selectedIndex).isEqualTo(1) assertThat(selectedId).isEqualTo(2) } }
packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt +5 −2 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import android.content.pm.ApplicationInfo import android.icu.text.CollationKey import androidx.compose.runtime.Composable import androidx.compose.runtime.State import com.android.settingslib.spa.widget.ui.SpinnerOption import com.android.settingslib.spaprivileged.template.app.AppListItem import com.android.settingslib.spaprivileged.template.app.AppListItemModel import kotlinx.coroutines.flow.Flow Loading @@ -23,7 +24,7 @@ interface AppListModel<T : AppRecord> { * * Default no spinner will be shown. */ fun getSpinnerOptions(): List<String> = emptyList() fun getSpinnerOptions(recordList: List<T>): List<SpinnerOption> = emptyList() /** * Loads the extra info for the App List, and generates the [AppRecord] List. Loading @@ -42,8 +43,10 @@ interface AppListModel<T : AppRecord> { * This function is called when the App List's loading is finished and displayed to the user. * * Could do some pre-cache here. * * @return true to enable pre-fetching app labels. */ suspend fun onFirstLoaded(recordList: List<T>) {} suspend fun onFirstLoaded(recordList: List<T>) = false /** * Gets the comparator to sort the App List. Loading