Before Jetpack Compose I was using Navigation Component in the projects in View system world.
Apps had only one activity - toolbar, bottom bar and drawer were added only to this activity once.
Apps could have many screens (fragments) and only top destination fragments were displaying bottom bar and allowed drawer, for other fragments it was hidden.
All of that was handled with Navigation Component like this from the activity:
fun initNavigation() {
val topLevelDestinationFragments = setOf(R.id.homeFragment, R.id.photosFragment)
appBarConfiguration = AppBarConfiguration(
topLevelDestinationFragments,
binding.drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
binding.drawerNavigationView.setupWithNavController(navController)
binding.bottomNavigationView.setupWithNavController(navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
// don't change bars if a dialog fragment
if (destination is FloatingWindow) {
return@addOnDestinationChangedListener
}
// Google solution to hide navigation bars
// https://developer.android.com/guide/navigation/navigation-ui#listen_for_navigation_events
val allowBottomAndDrawerNavigation = destination.id in topLevelDestinationFragments
binding.bottomNavigationView.isVisible = allowBottomAndDrawerNavigation
binding.drawerLayout.setDrawerLockMode(
if (allowBottomAndDrawerNavigation) {
DrawerLayout.LOCK_MODE_UNLOCKED
} else {
DrawerLayout.LOCK_MODE_LOCKED_CLOSED
}
)
binding.toolbar.isVisible = // if we need to hide toolbar for specific fragments
}
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
Quite easy, no need to add separately toolbar for each fragment and so on (so it was added only to the layout of the activity, it wasn't added to each layout of each fragment)
Navigation Component automatically handles back and menu (for drawer) buttons on the toolbar, automatically switches between them because it knows top destinations
Is there something similar for Compose?
Because I checked official Google sample "JetNews" from CodeLabs git https://github.com/googlecodelabs/android-compose-codelabs/tree/end/AccessibilityCodelab/app/src/main/java/com/example/jetnews/ui
They use compose navigation there but they separately added Scaffold
for each compose screen.
For example "Home" compose screen has it own Scaffold
Scaffold(
scaffoldState = scaffoldState,
topBar = {
val title = stringResource(id = R.string.app_name)
InsetAwareTopAppBar(
title = { Text(text = title) },
navigationIcon = {
IconButton(onClick = { coroutineScope.launch { openDrawer() } }) {
Icon(
painter = painterResource(R.drawable.ic_jetnews_logo),
contentDescription = stringResource(R.string.cd_open_navigation_drawer)
)
}
}
)
}
)
And "Article" compose screen has it own Scaffold
Scaffold(
topBar = {
InsetAwareTopAppBar(
title = {
Text(
text = "Published in: ${post.publication?.name}",
style = MaterialTheme.typography.subtitle2,
color = LocalContentColor.current
)
},
navigationIcon = {
IconButton(onClick = onBack) {
Icon(
imageVector = Icons.Filled.ArrowBack,
// Step 4: Content descriptions
contentDescription = stringResource(
R.string.cd_navigate_up
)
)
}
}
)
}
)
So basically here we duplicate the code and define manually different logic for navigationIcon
(icon and action) of toolbar
Does it mean that if we have some details screens with back arrow button and without bottom bar then we define a separate Scaffold
and can't just use one Scaffold
for all compose screens of the app?
Or can we implement the same logic as well for all compose screens as we did with Navigation Component in View system? Also setting top destinations, hiding bottom bar and locking drawer for non top destinations.