Create Category & CategoryTitle for SpaLib

Bug: 244122804
Test: Manual with Gallery App
Change-Id: I8b22de50f8b1bb064963fea1271ff7494d0df0f9
This commit is contained in:
Chaohui Wang
2022-09-19 13:41:48 +08:00
parent dd6945aad8
commit 54038d8a83
5 changed files with 248 additions and 0 deletions

View File

@@ -30,6 +30,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.ui.CategoryPageProvider
import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider
object SpaEnvironment {
@@ -49,6 +50,7 @@ object SpaEnvironment {
SettingsPagerPageProvider,
FooterPageProvider,
IllustrationPageProvider,
CategoryPageProvider,
),
rootPages = listOf(
SettingsPage.create(HomePageProvider.name)

View File

@@ -32,6 +32,7 @@ import com.android.settingslib.spa.gallery.page.IllustrationPageProvider
import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider
import com.android.settingslib.spa.gallery.page.SliderPageProvider
import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider
import com.android.settingslib.spa.gallery.ui.CategoryPageProvider
import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider
import com.android.settingslib.spa.widget.scaffold.HomeScaffold
@@ -48,6 +49,7 @@ object HomePageProvider : SettingsPageProvider {
SettingsPagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
FooterPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
IllustrationPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
CategoryPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
)
}

View File

@@ -0,0 +1,96 @@
/*
* 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.ui
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.tooling.preview.Preview
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.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.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category
import com.android.settingslib.spa.widget.ui.CategoryTitle
private const val TITLE = "Sample Category"
object CategoryPageProvider : SettingsPageProvider {
override val name = "Spinner"
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
.setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
override val onClick = navigator(name)
})
}
}
@Composable
override fun Page(arguments: Bundle?) {
CategoryPage()
}
}
@Composable
private fun CategoryPage() {
RegularScaffold(title = TITLE) {
CategoryTitle("Category A")
Preference(remember {
object : PreferenceModel {
override val title = "Preference 1"
override val summary = stateOf("Summary 1")
}
})
Preference(remember {
object : PreferenceModel {
override val title = "Preference 2"
override val summary = stateOf("Summary 2")
}
})
Category("Category B") {
Preference(remember {
object : PreferenceModel {
override val title = "Preference 3"
override val summary = stateOf("Summary 3")
}
})
Preference(remember {
object : PreferenceModel {
override val title = "Preference 4"
override val summary = stateOf("Summary 4")
}
})
}
}
}
@Preview(showBackground = true)
@Composable
private fun SpinnerPagePreview() {
SettingsTheme {
SpinnerPageProvider.Page(null)
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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.widget.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
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.layout.onGloballyPositioned
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsTheme
/**
* A category title that is placed before a group of similar items.
*/
@Composable
fun CategoryTitle(title: String) {
Text(
text = title,
modifier = Modifier.padding(
start = SettingsDimension.itemPaddingStart,
top = 20.dp,
end = SettingsDimension.itemPaddingEnd,
bottom = 8.dp,
),
color = SettingsTheme.colorScheme.categoryTitle,
style = MaterialTheme.typography.labelMedium,
)
}
/**
* A container that is used to group similar items. A [Category] displays a [CategoryTitle] and
* visually separates groups of items.
*/
@Composable
fun Category(title: String, content: @Composable ColumnScope.() -> Unit) {
Column {
var displayTitle by remember { mutableStateOf(false) }
if (displayTitle) CategoryTitle(title = title)
Column(
modifier = Modifier.onGloballyPositioned { coordinates ->
displayTitle = coordinates.size.height > 0
},
content = content,
)
}
}
@Preview
@Composable
private fun CategoryPreview() {
SettingsTheme {
CategoryTitle("Appearance")
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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.widget.ui
import androidx.compose.runtime.remember
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class CategoryTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun categoryTitle() {
composeTestRule.setContent {
CategoryTitle(title = "CategoryTitle")
}
composeTestRule.onNodeWithText("CategoryTitle").assertIsDisplayed()
}
@Test
fun category_hasContent_titleDisplayed() {
composeTestRule.setContent {
Category(title = "CategoryTitle") {
Preference(remember {
object : PreferenceModel {
override val title = "Some Preference"
override val summary = stateOf("Some summary")
}
})
}
}
composeTestRule.onNodeWithText("CategoryTitle").assertIsDisplayed()
}
@Test
fun category_noContent_titleNotDisplayed() {
composeTestRule.setContent {
Category(title = "CategoryTitle") {}
}
composeTestRule.onNodeWithText("CategoryTitle").assertDoesNotExist()
}
}