Rename SpaLib Codelab to SpaLib Gallery
Bug: 235727273
Test: Build
Change-Id: I98eb51cbaadf0dbfe61562e07061dd5c4d476f47
diff --git a/packages/SettingsLib/Spa/gallery/Android.bp b/packages/SettingsLib/Spa/gallery/Android.bp
new file mode 100644
index 0000000..bc083c9
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2022 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 {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_app {
+ name: "SpaLibGallery",
+
+ srcs: ["src/**/*.kt"],
+
+ static_libs: [
+ "SpaLib",
+ "androidx.compose.runtime_runtime",
+ ],
+ kotlincflags: ["-Xjvm-default=all"],
+ platform_apis: true,
+ min_sdk_version: "31",
+}
diff --git a/packages/SettingsLib/Spa/gallery/AndroidManifest.xml b/packages/SettingsLib/Spa/gallery/AndroidManifest.xml
new file mode 100644
index 0000000..cde47f2
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.spa.gallery">
+
+ <application
+ android:label="@string/app_name"
+ android:supportsRtl="true"
+ android:theme="@style/Theme.SpaLib.DayNight">
+ <activity
+ android:name="com.android.settingslib.spa.gallery.MainActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/packages/SettingsLib/Spa/gallery/build.gradle b/packages/SettingsLib/Spa/gallery/build.gradle
new file mode 100644
index 0000000..98e6745
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/build.gradle
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2022 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.
+ */
+
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+}
+
+android {
+ namespace 'com.android.settingslib.spa.gallery'
+ compileSdk 33
+
+ defaultConfig {
+ applicationId "com.android.settingslib.spa.gallery"
+ minSdk spa_min_sdk
+ targetSdk 33
+ versionCode 1
+ versionName "1.0"
+ }
+
+ sourceSets {
+ main {
+ kotlin {
+ srcDir "src"
+ }
+ res.srcDirs = ["res"]
+ manifest.srcFile "AndroidManifest.xml"
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ freeCompilerArgs = ["-Xjvm-default=all"]
+ }
+ buildFeatures {
+ compose true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion jetpack_compose_version
+ }
+ packagingOptions {
+ resources {
+ excludes += '/META-INF/{AL2.0,LGPL2.1}'
+ }
+ }
+}
+
+dependencies {
+ implementation(project(":spa"))
+}
diff --git a/packages/SettingsLib/Spa/gallery/res/values/strings.xml b/packages/SettingsLib/Spa/gallery/res/values/strings.xml
new file mode 100644
index 0000000..510e6c2
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ Copyright (C) 2022 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.
+ -->
+<resources>
+ <!-- Gallery App name. [DO NOT TRANSLATE] -->
+ <string name="app_name" translatable="false">SpaLib Gallery</string>
+</resources>
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/MainActivity.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/MainActivity.kt
new file mode 100644
index 0000000..7db53b4
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/MainActivity.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 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.gallery
+
+import com.android.settingslib.spa.framework.SpaActivity
+import com.android.settingslib.spa.gallery.page.galleryPageRepository
+
+class MainActivity : SpaActivity(galleryPageRepository)
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
new file mode 100644
index 0000000..937e594
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 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.gallery.page
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.navigation.NavType
+import androidx.navigation.navArgument
+import com.android.settingslib.spa.framework.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.compose.toState
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+
+private const val STRING_PARAM_NAME = "stringParam"
+private const val INT_PARAM_NAME = "intParam"
+
+object ArgumentPageProvider : SettingsPageProvider {
+ override val name = Destinations.Argument
+
+ override val arguments = listOf(
+ navArgument(STRING_PARAM_NAME) { type = NavType.StringType },
+ navArgument(INT_PARAM_NAME) { type = NavType.IntType },
+ )
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ ArgumentPage(
+ stringParam = arguments!!.getString(STRING_PARAM_NAME, "default"),
+ intParam = arguments.getInt(INT_PARAM_NAME),
+ )
+ }
+
+ @Composable
+ fun EntryItem(stringParam: String, intParam: Int) {
+ Preference(object : PreferenceModel {
+ override val title = "Sample page with arguments"
+ override val summary =
+ "$STRING_PARAM_NAME=$stringParam, $INT_PARAM_NAME=$intParam".toState()
+ override val onClick = navigator("${Destinations.Argument}/$stringParam/$intParam")
+ })
+ }
+}
+
+@Composable
+fun ArgumentPage(stringParam: String, intParam: Int) {
+ Column {
+ Preference(object : PreferenceModel {
+ override val title = "String param value"
+ override val summary = stringParam.toState()
+ })
+
+ Preference(object : PreferenceModel {
+ override val title = "Int param value"
+ override val summary = intParam.toString().toState()
+ })
+
+ ArgumentPageProvider.EntryItem(stringParam = "foo", intParam = intParam + 1)
+
+ ArgumentPageProvider.EntryItem(stringParam = "bar", intParam = intParam + 1)
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun ArgumentPagePreview() {
+ SettingsTheme {
+ ArgumentPage(stringParam = "foo", intParam = 0)
+ }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
new file mode 100644
index 0000000..143c365
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 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.gallery.page
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.compose.stateOf
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.ui.Footer
+
+object FooterPageProvider : SettingsPageProvider {
+ override val name = "Footer"
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ FooterPage()
+ }
+
+ @Composable
+ fun EntryItem() {
+ Preference(object : PreferenceModel {
+ override val title = "Sample Footer"
+ override val onClick = navigator(name)
+ })
+ }
+}
+
+@Composable
+private fun FooterPage() {
+ Column(Modifier.verticalScroll(rememberScrollState())) {
+ Preference(remember {
+ object : PreferenceModel {
+ override val title = "Some Preference"
+ override val summary = stateOf("Some summary")
+ }
+ })
+ Footer(footerText = "Footer text always at the end of page.")
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun FooterPagePreview() {
+ SettingsTheme {
+ FooterPage()
+ }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/HomePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/HomePage.kt
new file mode 100644
index 0000000..0d17cd2
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/HomePage.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 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.gallery.page
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.gallery.R
+
+object HomePageProvider : SettingsPageProvider {
+ override val name = Destinations.Home
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ HomePage()
+ }
+}
+
+@Composable
+private fun HomePage() {
+ Column {
+ Text(
+ text = stringResource(R.string.app_name),
+ modifier = Modifier.padding(SettingsDimension.itemPadding),
+ color = MaterialTheme.colorScheme.onSurface,
+ style = MaterialTheme.typography.headlineMedium,
+ )
+
+ PreferencePageProvider.EntryItem()
+ SwitchPreferencePageProvider.EntryItem()
+ ArgumentPageProvider.EntryItem(stringParam = "foo", intParam = 0)
+
+ SliderPageProvider.EntryItem()
+ FooterPageProvider.EntryItem()
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun HomeScreenPreview() {
+ SettingsTheme {
+ HomePage()
+ }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PageRepository.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PageRepository.kt
new file mode 100644
index 0000000..8f38d82
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PageRepository.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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.gallery.page
+
+import com.android.settingslib.spa.framework.api.SettingsPageRepository
+
+object Destinations {
+ const val Home = "Home"
+ const val Preference = "Preference"
+ const val SwitchPreference = "SwitchPreference"
+ const val Argument = "Argument"
+ const val Slider = "Slider"
+}
+
+val galleryPageRepository = SettingsPageRepository(
+ allPages = listOf(
+ HomePageProvider,
+ PreferencePageProvider,
+ SwitchPreferencePageProvider,
+ ArgumentPageProvider,
+ SliderPageProvider,
+ FooterPageProvider,
+ ),
+ startDestination = Destinations.Home,
+)
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt
new file mode 100644
index 0000000..3077a15
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2022 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.gallery.page
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.produceState
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.compose.toState
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import kotlinx.coroutines.delay
+
+object PreferencePageProvider : SettingsPageProvider {
+ override val name = Destinations.Preference
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ PreferencePage()
+ }
+
+ @Composable
+ fun EntryItem() {
+ Preference(object : PreferenceModel {
+ override val title = "Sample Preference"
+ override val onClick = navigator(Destinations.Preference)
+ })
+ }
+}
+
+@Composable
+private fun PreferencePage() {
+ Column(Modifier.verticalScroll(rememberScrollState())) {
+ Preference(object : PreferenceModel {
+ override val title = "Preference"
+ })
+
+ Preference(object : PreferenceModel {
+ override val title = "Preference"
+ override val summary = "With summary".toState()
+ })
+
+ Preference(object : PreferenceModel {
+ override val title = "Preference"
+ override val summary = produceState(initialValue = " ") {
+ delay(1000L)
+ value = "Async summary"
+ }
+ })
+
+ var count by remember { mutableStateOf(0) }
+ Preference(object : PreferenceModel {
+ override val title = "Click me"
+ override val summary = derivedStateOf { count.toString() }
+ override val onClick: (() -> Unit) = { count++ }
+ })
+
+ var ticks by remember { mutableStateOf(0) }
+ LaunchedEffect(ticks) {
+ delay(1000L)
+ ticks++
+ }
+ Preference(object : PreferenceModel {
+ override val title = "Ticker"
+ override val summary = derivedStateOf { ticks.toString() }
+ })
+
+ Preference(object : PreferenceModel {
+ override val title = "Disabled"
+ override val summary = "Disabled".toState()
+ override val enabled = false.toState()
+ })
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun PreferencePagePreview() {
+ SettingsTheme {
+ PreferencePage()
+ }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
new file mode 100644
index 0000000..9bcac1b
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2022 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.gallery.page
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.AccessAlarm
+import androidx.compose.material.icons.outlined.MusicNote
+import androidx.compose.material.icons.outlined.MusicOff
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.ui.SettingsSlider
+import com.android.settingslib.spa.widget.ui.SettingsSliderModel
+
+object SliderPageProvider : SettingsPageProvider {
+ override val name = Destinations.Slider
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ SliderPage()
+ }
+
+ @Composable
+ fun EntryItem() {
+ Preference(object : PreferenceModel {
+ override val title = "Sample Slider"
+ override val onClick = navigator(Destinations.Slider)
+ })
+ }
+}
+
+@Composable
+private fun SliderPage() {
+ Column(Modifier.verticalScroll(rememberScrollState())) {
+ SettingsSlider(object : SettingsSliderModel {
+ override val title = "Slider"
+ override val initValue = 40
+ })
+
+ SettingsSlider(object : SettingsSliderModel {
+ override val title = "Slider with icon"
+ override val initValue = 30
+ override val onValueChangeFinished = {
+ println("onValueChangeFinished")
+ }
+ override val icon = Icons.Outlined.AccessAlarm
+ })
+
+ val initValue = 0
+ var icon by remember { mutableStateOf(Icons.Outlined.MusicOff) }
+ var sliderPosition by remember { mutableStateOf(initValue) }
+ SettingsSlider(object : SettingsSliderModel {
+ override val title = "Slider with changeable icon"
+ override val initValue = initValue
+ override val onValueChange = { it: Int ->
+ sliderPosition = it
+ icon = if (it > 0) Icons.Outlined.MusicNote else Icons.Outlined.MusicOff
+ }
+ override val onValueChangeFinished = {
+ println("onValueChangeFinished: the value is $sliderPosition")
+ }
+ override val icon = icon
+ })
+
+ SettingsSlider(object : SettingsSliderModel {
+ override val title = "Slider with steps"
+ override val initValue = 2
+ override val valueRange = 1..5
+ override val showSteps = true
+ })
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun SliderPagePreview() {
+ SettingsTheme {
+ SliderPage()
+ }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt
new file mode 100644
index 0000000..b6f7258
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 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.gallery.page
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.produceState
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.compose.stateOf
+import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+import kotlinx.coroutines.delay
+
+object SwitchPreferencePageProvider : SettingsPageProvider {
+ override val name = Destinations.SwitchPreference
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ SwitchPreferencePage()
+ }
+
+ @Composable
+ fun EntryItem() {
+ Preference(object : PreferenceModel {
+ override val title = "Sample SwitchPreference"
+ override val onClick = navigator(Destinations.SwitchPreference)
+ })
+ }
+}
+
+@Composable
+private fun SwitchPreferencePage() {
+ Column(Modifier.verticalScroll(rememberScrollState())) {
+ SampleSwitchPreference()
+ SampleSwitchPreferenceWithSummary()
+ SampleSwitchPreferenceWithAsyncSummary()
+ SampleNotChangeableSwitchPreference()
+ }
+}
+
+@Composable
+private fun SampleSwitchPreference() {
+ val checked = rememberSaveable { mutableStateOf(false) }
+ SwitchPreference(remember {
+ object : SwitchPreferenceModel {
+ override val title = "SwitchPreference"
+ override val checked = checked
+ override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+ }
+ })
+}
+
+@Composable
+private fun SampleSwitchPreferenceWithSummary() {
+ val checked = rememberSaveable { mutableStateOf(true) }
+ SwitchPreference(remember {
+ object : SwitchPreferenceModel {
+ override val title = "SwitchPreference"
+ override val summary = stateOf("With summary")
+ override val checked = checked
+ override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+ }
+ })
+}
+
+@Composable
+private fun SampleSwitchPreferenceWithAsyncSummary() {
+ val checked = rememberSaveable { mutableStateOf(true) }
+ val summary = produceState(initialValue = " ") {
+ delay(1000L)
+ value = "Async summary"
+ }
+ SwitchPreference(remember {
+ object : SwitchPreferenceModel {
+ override val title = "SwitchPreference"
+ override val summary = summary
+ override val checked = checked
+ override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+ }
+ })
+}
+
+@Composable
+private fun SampleNotChangeableSwitchPreference() {
+ val checked = rememberSaveable { mutableStateOf(true) }
+ SwitchPreference(remember {
+ object : SwitchPreferenceModel {
+ override val title = "SwitchPreference"
+ override val summary = stateOf("Not changeable")
+ override val changeable = stateOf(false)
+ override val checked = checked
+ override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+ }
+ })
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun SwitchPreferencePagePreview() {
+ SettingsTheme {
+ SwitchPreferencePage()
+ }
+}