Simon Stahl
06/09/2022, 1:59 AMpage/{pageName}
and then use pageName
to to render the correct data. I mostly wanted to use navigation because of the built in backstack
@Composable
fun NavigationTest() {
val navController = rememberNavController()
Scaffold(
bottomBar = { SimpleBottomNav(navController) }
) { innerPadding ->
NavHost(navController, startDestination = "page/{pageName}", Modifier.padding(innerPadding)) {
composable(
"page/{pageName}",
arguments = listOf(navArgument("pageName") { defaultValue = "profile" })
) { backStackEntry ->
val pageName = backStackEntry.arguments?.getString("pageName")
if (pageName != null) {
PageContent(name = pageName)
} else {
Text(text = "No page name")
}
}
}
}
}
See SimpleBottomNav
code in the comments. The main issues that I have is that 1. popUpTo()
does not seem to work properly when the startDestination has an argument in it and 2. the compose context seems to be shared between the different pages. E.g. when i use a LazyList in them, they all share the same scroll state. Did anyone ever have the same issues or has a working example for something similar?@Composable
fun SimpleBottomNav(navController: NavHostController) {
var selectedRoute by remember { mutableStateOf("profile") }
BottomNavigation {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
listOf("profile", "for-you", "settings").forEach { pageName ->
BottomNavigationItem(
icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
label = { Text(pageName) },
selected = selectedRoute == pageName,
onClick = {
selectedRoute = pageName
navController.navigate("page/$pageName") {
// TODO popping doesn't seem to work with start page containing an argument
// popUpTo(navController.graph.findStartDestination().id) {
// saveState = true
// }
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
Ian Lake
06/09/2022, 2:11 AMSimon Stahl
06/09/2022, 2:28 AMpageName
is used inside `PageContent`'s VM to load the data (page names are loaded dynamically too at app start). This works great, but like i mentioned, I am mostly looking for a way to preserve the page state in a backstack when navigating away so it can be restored when navigating back. Navigation has that build in and i was hoping I could use it.
I mean, one page is known, i just add an argument to define its data. Are you saying this is not the intended use of navigation?Ian Lake
06/09/2022, 2:37 AMSimon Stahl
06/09/2022, 2:52 AMIan Lake
06/09/2022, 2:57 AMIt's all the same composable that changes its look according to the data loaded with the pageName
That sounds like different composables. Specifically, different composables using a slot based API
Simon Stahl
06/09/2022, 3:28 AMPageContent
composable plugs together different existing composables, but not in a way that they could be defined as navigation targets. Assume they are completely dynamic - they could contain just one composable, a list, grid or anything else.Ian Lake
06/09/2022, 3:46 AMColton Idle
06/09/2022, 4:36 AMIan Lake
06/09/2022, 4:40 AMlaunchSingleTop
, if you want to disable that behavior)popUpTo
takes one of the route patterns - i.e., that page/{pageName}
and popUpTo
will only pop up to the topmost copy of that destination...not up multiple copies of that destinationSimon Stahl
06/09/2022, 5:12 AM@Composable
fun NavigationTest() {
val navController = rememberNavController()
Scaffold(
bottomBar = { SimpleBottomNav(navController) }
) { innerPadding ->
val bottomNavTabs = getServerBottomNavTabs()
NavHost(
navController,
startDestination = "page/${bottomNavTabs[0]}",
Modifier.padding(innerPadding)
) {
bottomNavTabs.forEach { pageName ->
composable("page/$pageName") {
PageContent(name = pageName)
}
}
}
}
}
Ian Lake
06/10/2022, 10:03 PMpage/$pageName
syntax - just use pageName
as the route:
fun NavigationTest() {
val navController = rememberNavController()
Scaffold(
bottomBar = { SimpleBottomNav(navController) }
) { innerPadding ->
val bottomNavTabs = getServerBottomNavTabs()
NavHost(
navController,
startDestination = bottomNavTabs[0],
Modifier.padding(innerPadding)
) {
// Your bottom nav tabs use a fixed route
bottomNavTabs.forEach { pageName ->
composable("$pageName") {
PageContent(name = pageName)
}
}
// These are your completely dynamic screens that don't have a fixed route
composable("page/{$pageName}) { backStackEntry ->
val pageName = backStackEntry.arguments?.getString("pageName")
if (pageName != null) {
PageContent(name = pageName)
} else {
Text(text = "No page name")
}
}
}
}
}
Simon Stahl
06/10/2022, 11:22 PM