Represent the Gallery screen hierarchy as a tree

This CL changes the Gallery app screens to be a tree instead of a list.
This will allow adding sub-menus to the gallery app in case we want
multiple different screens for a single feature, which is the case for
the People activity/screens.

Bug: 238993727
Test: Builds
Change-Id: Idd28fd5a0fa79fd32ab1f8a95ed8c16fa2f465ac
This commit is contained in:
Jordan Demeulenaere
2022-07-25 17:30:20 +02:00
parent 0facbc9835
commit f9e90fd2ab
3 changed files with 115 additions and 77 deletions

View File

@@ -23,36 +23,38 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.android.systemui.compose.theme.SystemUITheme
enum class Screen {
Home,
Typography,
MaterialColors,
AndroidColors,
ExampleFeature,
/** The gallery app screens. */
object GalleryAppScreens {
val Typography = ChildScreen("typography") { TypographyScreen() }
val MaterialColors = ChildScreen("material_colors") { MaterialColorsScreen() }
val AndroidColors = ChildScreen("android_colors") { AndroidColorsScreen() }
val ExampleFeature = ChildScreen("example_feature") { ExampleFeatureScreen() }
val Home =
ParentScreen(
"home",
mapOf(
"Typography" to Typography,
"Material colors" to MaterialColors,
"Android colors" to AndroidColors,
"Example feature" to ExampleFeature,
)
)
}
/** The main content of the app, that shows the [HomeScreen] by default. */
/** The main content of the app, that shows [GalleryAppScreens.Home] by default. */
@Composable
private fun MainContent() {
Box(Modifier.fillMaxSize()) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Screen.Home.name,
startDestination = GalleryAppScreens.Home.identifier,
) {
composable(Screen.Home.name) {
HomeScreen(
onScreenSelected = { navController.navigate(it.name) },
)
}
composable(Screen.Typography.name) { TypographyScreen() }
composable(Screen.MaterialColors.name) { MaterialColorsScreen() }
composable(Screen.AndroidColors.name) { AndroidColorsScreen() }
composable(Screen.ExampleFeature.name) { ExampleFeatureScreen() }
screen(GalleryAppScreens.Home, navController)
}
}
}

View File

@@ -1,59 +0,0 @@
/*
* 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.systemui.compose.gallery
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
/** The home screen shown when starting the app. */
@Composable
fun HomeScreen(onScreenSelected: (Screen) -> Unit) {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Screen.values()
.filter { it != Screen.Home }
.forEach { screen ->
item {
Surface(
Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.secondaryContainer,
shape = CircleShape,
) {
Column(
Modifier.clickable { onScreenSelected(screen) }.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(screen.name)
}
}
}
}
}
}

View File

@@ -0,0 +1,95 @@
/*
* 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.systemui.compose.gallery
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
/**
* A screen in an app. It is either an [ParentScreen] which lists its child screens to navigate to
* them or a [ChildScreen] which shows some content.
*/
sealed class Screen(val identifier: String)
class ParentScreen(
identifier: String,
val children: Map<String, Screen>,
) : Screen(identifier)
class ChildScreen(
identifier: String,
val content: @Composable (NavController) -> Unit,
) : Screen(identifier)
/** Create the navigation graph for [screen]. */
fun NavGraphBuilder.screen(screen: Screen, navController: NavController) {
when (screen) {
is ChildScreen -> composable(screen.identifier) { screen.content(navController) }
is ParentScreen -> {
val menuRoute = "${screen.identifier}_menu"
navigation(startDestination = menuRoute, route = screen.identifier) {
// The menu to navigate to one of the children screens.
composable(menuRoute) { ScreenMenu(screen, navController) }
// The content of the child screens.
screen.children.forEach { (_, child) -> screen(child, navController) }
}
}
}
}
@Composable
private fun ScreenMenu(
screen: ParentScreen,
navController: NavController,
) {
LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) {
screen.children.forEach { (name, child) ->
item {
Surface(
Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.secondaryContainer,
shape = CircleShape,
) {
Column(
Modifier.clickable { navController.navigate(child.identifier) }
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(name)
}
}
}
}
}
}