Loading packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt +2 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider import com.android.settingslib.spa.gallery.preference.PreferencePageProvider import com.android.settingslib.spa.gallery.preference.SwitchPreferencePageProvider import com.android.settingslib.spa.gallery.preference.TwoTargetSwitchPreferencePageProvider import com.android.settingslib.spa.gallery.preference.ZeroStatePreferencePageProvider import com.android.settingslib.spa.gallery.scaffold.PagerMainPageProvider import com.android.settingslib.spa.gallery.scaffold.SearchScaffoldPageProvider import com.android.settingslib.spa.gallery.scaffold.SuwScaffoldPageProvider Loading Loading @@ -83,6 +84,7 @@ class GallerySpaEnvironment(context: Context) : SpaEnvironment(context) { MainSwitchPreferencePageProvider, ListPreferencePageProvider, TwoTargetSwitchPreferencePageProvider, ZeroStatePreferencePageProvider, ArgumentPageProvider, SliderPageProvider, SpinnerPageProvider, Loading packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMainPageProvider.kt +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ object PreferenceMainPageProvider : SettingsPageProvider { ListPreferencePageProvider.buildInjectEntry().setLink(fromPage = owner).build(), TwoTargetSwitchPreferencePageProvider.buildInjectEntry() .setLink(fromPage = owner).build(), ZeroStatePreferencePageProvider.buildInjectEntry().setLink(fromPage = owner).build(), IntroPreferencePageProvider.buildInjectEntry().setLink(fromPage = owner).build(), ) } Loading packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/ZeroStatePreferencePageProvider.kt 0 → 100644 +92 −0 Original line number Diff line number Diff line /* * 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.gallery.preference import android.os.Bundle import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.History import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import com.android.settingslib.spa.framework.common.SettingsEntry import com.android.settingslib.spa.framework.common.SettingsEntryBuilder import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.createSettingsPage 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.preference.ZeroStatePreference private const val TITLE = "Sample ZeroStatePreference" object ZeroStatePreferencePageProvider : SettingsPageProvider { override val name = "ZeroStatePreference" private val owner = createSettingsPage() override fun buildEntry(arguments: Bundle?): List<SettingsEntry> { val entryList = mutableListOf<SettingsEntry>() entryList.add( SettingsEntryBuilder.create("ZeroStatePreference", owner) .setUiLayoutFn { SampleZeroStatePreference() }.build() ) return entryList } fun buildInjectEntry(): SettingsEntryBuilder { return SettingsEntryBuilder.createInject(owner) .setUiLayoutFn { Preference(object : PreferenceModel { override val title = TITLE override val onClick = navigator(name) }) } } override fun getTitle(arguments: Bundle?): String { return TITLE } } @Composable private fun SampleZeroStatePreference() { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { ZeroStatePreference( Icons.Filled.History, "No recent search history", "Description" ) } } @Preview(showBackground = true) @Composable private fun SwitchPreferencePagePreview() { SettingsTheme { ZeroStatePreferencePageProvider.Page(null) } } packages/SettingsLib/Spa/spa/build.gradle.kts +1 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ dependencies { api("androidx.navigation:navigation-compose:2.8.0-rc01") api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha") api("com.google.android.material:material:1.11.0") api("androidx.graphics:graphics-shapes-android:1.0.1") debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion") implementation("com.airbnb.android:lottie-compose:6.4.0") Loading packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ZeroStatePreference.kt 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * 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.widget.preference import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.History import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Matrix import androidx.compose.ui.graphics.Outline import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.asComposePath import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.graphics.shapes.CornerRounding import androidx.graphics.shapes.RoundedPolygon import androidx.graphics.shapes.star import androidx.graphics.shapes.toPath @Composable fun ZeroStatePreference(icon: ImageVector, text: String? = null, description: String? = null) { val zeroStateShape = remember { RoundedPolygon.star( numVerticesPerRadius = 6, innerRadius = 0.75f, rounding = CornerRounding(0.3f) ) } val clip = remember(zeroStateShape) { RoundedPolygonShape(polygon = zeroStateShape) } Column(horizontalAlignment = Alignment.CenterHorizontally) { Box( modifier = Modifier .clip(clip) .background(MaterialTheme.colorScheme.primary) .size(160.dp) ) { Icon( imageVector = icon, modifier = Modifier .align(Alignment.Center) .size(72.dp), tint = MaterialTheme.colorScheme.onPrimary, contentDescription = null, ) } if (text != null) { Text( text = text, textAlign = TextAlign.Center, style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(top = 24.dp), ) } if (description != null) { Box { Text( text = description, textAlign = TextAlign.Center, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } } } @Preview @Composable private fun ZeroStatePreferencePreview() { ZeroStatePreference( Icons.Filled.History, "No recent search history", "Description" ) } class RoundedPolygonShape( private val polygon: RoundedPolygon, private var matrix: Matrix = Matrix() ) : Shape { private var path = Path() override fun createOutline( size: Size, layoutDirection: LayoutDirection, density: Density ): Outline { path.rewind() path = polygon.toPath().asComposePath() matrix.reset() matrix.scale(size.width / 2f, size.height / 2f) matrix.translate(1f, 1f) matrix.rotateZ(30.0f) path.transform(matrix) return Outline.Generic(path) } } No newline at end of file Loading
packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt +2 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider import com.android.settingslib.spa.gallery.preference.PreferencePageProvider import com.android.settingslib.spa.gallery.preference.SwitchPreferencePageProvider import com.android.settingslib.spa.gallery.preference.TwoTargetSwitchPreferencePageProvider import com.android.settingslib.spa.gallery.preference.ZeroStatePreferencePageProvider import com.android.settingslib.spa.gallery.scaffold.PagerMainPageProvider import com.android.settingslib.spa.gallery.scaffold.SearchScaffoldPageProvider import com.android.settingslib.spa.gallery.scaffold.SuwScaffoldPageProvider Loading Loading @@ -83,6 +84,7 @@ class GallerySpaEnvironment(context: Context) : SpaEnvironment(context) { MainSwitchPreferencePageProvider, ListPreferencePageProvider, TwoTargetSwitchPreferencePageProvider, ZeroStatePreferencePageProvider, ArgumentPageProvider, SliderPageProvider, SpinnerPageProvider, Loading
packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMainPageProvider.kt +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ object PreferenceMainPageProvider : SettingsPageProvider { ListPreferencePageProvider.buildInjectEntry().setLink(fromPage = owner).build(), TwoTargetSwitchPreferencePageProvider.buildInjectEntry() .setLink(fromPage = owner).build(), ZeroStatePreferencePageProvider.buildInjectEntry().setLink(fromPage = owner).build(), IntroPreferencePageProvider.buildInjectEntry().setLink(fromPage = owner).build(), ) } Loading
packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/ZeroStatePreferencePageProvider.kt 0 → 100644 +92 −0 Original line number Diff line number Diff line /* * 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.gallery.preference import android.os.Bundle import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.History import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import com.android.settingslib.spa.framework.common.SettingsEntry import com.android.settingslib.spa.framework.common.SettingsEntryBuilder import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.createSettingsPage 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.preference.ZeroStatePreference private const val TITLE = "Sample ZeroStatePreference" object ZeroStatePreferencePageProvider : SettingsPageProvider { override val name = "ZeroStatePreference" private val owner = createSettingsPage() override fun buildEntry(arguments: Bundle?): List<SettingsEntry> { val entryList = mutableListOf<SettingsEntry>() entryList.add( SettingsEntryBuilder.create("ZeroStatePreference", owner) .setUiLayoutFn { SampleZeroStatePreference() }.build() ) return entryList } fun buildInjectEntry(): SettingsEntryBuilder { return SettingsEntryBuilder.createInject(owner) .setUiLayoutFn { Preference(object : PreferenceModel { override val title = TITLE override val onClick = navigator(name) }) } } override fun getTitle(arguments: Bundle?): String { return TITLE } } @Composable private fun SampleZeroStatePreference() { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { ZeroStatePreference( Icons.Filled.History, "No recent search history", "Description" ) } } @Preview(showBackground = true) @Composable private fun SwitchPreferencePagePreview() { SettingsTheme { ZeroStatePreferencePageProvider.Page(null) } }
packages/SettingsLib/Spa/spa/build.gradle.kts +1 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ dependencies { api("androidx.navigation:navigation-compose:2.8.0-rc01") api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha") api("com.google.android.material:material:1.11.0") api("androidx.graphics:graphics-shapes-android:1.0.1") debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion") implementation("com.airbnb.android:lottie-compose:6.4.0") Loading
packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ZeroStatePreference.kt 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * 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.widget.preference import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.History import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Matrix import androidx.compose.ui.graphics.Outline import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.asComposePath import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.graphics.shapes.CornerRounding import androidx.graphics.shapes.RoundedPolygon import androidx.graphics.shapes.star import androidx.graphics.shapes.toPath @Composable fun ZeroStatePreference(icon: ImageVector, text: String? = null, description: String? = null) { val zeroStateShape = remember { RoundedPolygon.star( numVerticesPerRadius = 6, innerRadius = 0.75f, rounding = CornerRounding(0.3f) ) } val clip = remember(zeroStateShape) { RoundedPolygonShape(polygon = zeroStateShape) } Column(horizontalAlignment = Alignment.CenterHorizontally) { Box( modifier = Modifier .clip(clip) .background(MaterialTheme.colorScheme.primary) .size(160.dp) ) { Icon( imageVector = icon, modifier = Modifier .align(Alignment.Center) .size(72.dp), tint = MaterialTheme.colorScheme.onPrimary, contentDescription = null, ) } if (text != null) { Text( text = text, textAlign = TextAlign.Center, style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(top = 24.dp), ) } if (description != null) { Box { Text( text = description, textAlign = TextAlign.Center, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } } } @Preview @Composable private fun ZeroStatePreferencePreview() { ZeroStatePreference( Icons.Filled.History, "No recent search history", "Description" ) } class RoundedPolygonShape( private val polygon: RoundedPolygon, private var matrix: Matrix = Matrix() ) : Shape { private var path = Path() override fun createOutline( size: Size, layoutDirection: LayoutDirection, density: Density ): Outline { path.rewind() path = polygon.toPath().asComposePath() matrix.reset() matrix.scale(size.width / 2f, size.height / 2f) matrix.translate(1f, 1f) matrix.rotateZ(30.0f) path.transform(matrix) return Outline.Generic(path) } } No newline at end of file