I'm trying to implement the following screen flow using Jetpack Compose + Jetpack Navigation:
Navigation concept
Actually, i am able to code two singles cases:
I'm not able to code the whole problem. In fact, i have an issue with the management of the NavHost. In the first case (SplashScreen -> HomeScreen) i need to call the NavHost at a high scope:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
//init the Navigation Controller for screen navigation
val navController = rememberNavController()
//setup the Navigation Graph
SetupNavGraph(navController)
while in the second case i need to call it in the innerPadding scope of the Scaffold composable:
fun MainScreen(navController: NavHostController) {
Scaffold(
bottomBar = {
BottomNavBar(navController)
}
) { //innerPadding scope
//setup the Navigation Graph
SetupNavGraph(navController)
}
}
Please assume that SetupNavGraph() function works as intended (call NavHost to generate the navigation tree)
NavHost without success.NavHost in setContent() i'm able to load the splashscreen and move to an empty BottomNavBar screen. If i click on the BottomNavElements i'm able to navigate to the child tabs (in the example above "Favorite","Music","Places", "News") but the BottomNavBar disappearsNavHost in the innerPadding scope because this is loaded only after switching to the main screen (in the example above "Favorite Tab" + BottomBarNav)The only workaround i found is generating the BottomNavBar composable in each of the BottomNav child tabs, but this generates a visible transition effect that i would like to avoid and, generally, doesn't seem a good practice.
Ok, i found a solution. This are the steps to achieve the desired result:
const val ROOT_ROUTE = "root"
@Composable
fun SetupRootNavGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = Screen.FirstScreen.route,
route = ROOT_ROUTE
) {
composable(Screen.FirstScreen.route) { FirstScreen(navController)}
composable(Screen.SecondScreen.route) { MainScreen(navController)}
}
}
const val BOTTOM_BAR_ROUTE = "bottomBar"
@Composable
fun SetupNavGraphBottomBar(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = BottomBarScreen.FirstElement.route,
route = BOTTOM_BAR_ROUTE
) {
composable(BottomBarScreen.FirstElement.route) { FirstElementScreen() }
composable(BottomBarScreen.SecondElement.route) { SecondElementScreen() }
composable(BottomBarScreen.ThirdElement.route) { ThirdElementScreen() }
}
}
NavController and the RootNavGraph after setContent() in your MainActivity. This will be in charge of the SplashScreen -> MainScreen navigation tree.class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
//init the Navigation Controller for screen navigation
val navController = rememberNavController()
//setup the Root Navigation Graph
SetupRootNavGraph(navController)
}
}
}
}
NavController in the Screen where you have your BottomNavBar ("MainScreen" in the example) and the assign to it the BottomNavGraph in the innerPadding scope.@Composable
fun MainScreen(navController: NavHostController) {
//Re-initialize the NavController to set a new NavGraph
val navControllerBottomBar = rememberNavController()
Scaffold(
bottomBar = {
BottomNavBar(navControllerBottomBar)
}
) {
//setup the Navigation Graph
SetupNavGraphBottomBar(navControllerBottomBar, user)
}
}
And this will work like charm! Of course you will need to structure your BottomNavBar in order to manage the navigation as documented on Official docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With