From f9e90fd2abf490c455a4b33fe8725ace62f083fc Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Mon, 25 Jul 2022 17:30:20 +0200 Subject: [PATCH] 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 --- .../systemui/compose/gallery/GalleryApp.kt | 38 ++++---- .../systemui/compose/gallery/HomeScreen.kt | 59 ------------ .../systemui/compose/gallery/Screen.kt | 95 +++++++++++++++++++ 3 files changed, 115 insertions(+), 77 deletions(-) delete mode 100644 packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt create mode 100644 packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/Screen.kt diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt index 0ac3a63aa9972..23badd0b44ba3 100644 --- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt @@ -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) } } } diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt deleted file mode 100644 index b1869da981367..0000000000000 --- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt +++ /dev/null @@ -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) - } - } - } - } - } -} diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/Screen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/Screen.kt new file mode 100644 index 0000000000000..467dac044b79c --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/Screen.kt @@ -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, +) : 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) + } + } + } + } + } +}