Konark Shivam
Konark Shivam

Reputation: 180

How to navigate from single screen to bottom screen(Screen-B with bottomNavigation) and then go to single screen in Jetpack Compose

I want to navigate from Screen-A(SplashScreen) to Screen-B(Having BottomNavigation containing 3 screens say HomeScreen, SearchScreen and ProfileScreen) and from bottomnavigation screen(i.e Screen-B) to another Screen(from home screen to detail screen without bottomnavBar)

I am not able to do this as in official docs there was simple explanation for this.

Here is the code i have done so far

This is my main activity class

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            My_grocery_app_composeTheme {
                MyApp()
            }
        }
    }
}


@Composable
fun MyApp() {
    val navController = rememberNavController()
    SetupNavGraph(navController = navController)
}

This is my navGraph

@Composable
fun SetupNavGraph(navController: NavHostController) {
    NavHost(
        navController = navController,
        route = ROOT_GRAPH_ROUTE,
        startDestination = Initial_Setup_Route
    ) {
        initialSetupNavGraph(navController)
        bottomNavigationNavGraph(navController)
    }
}


fun NavGraphBuilder.initialSetupNavGraph(navController: NavController) {
    navigation(startDestination = Screen.Splash.route, route = Initial_Setup_Route) {
        composable(Screen.Splash.route) {
            SplashScreen(navController = navController)
        }
        composable(Screen.BottomNavigation.route) {
            BottomNavScreen(navController = navController)
        }
        composable(Screen.Other.route) {
            OtherScreen()
        }
    }
}

//
fun NavGraphBuilder.bottomNavigationNavGraph(navController: NavController) {
    navigation(startDestination = Screen.Home.route, route = BottomNavigation_Route) {
        composable(Screen.Home.route) {
            HomeScreen()
        }
        composable(Screen.Search.route) {
            SearchScreen()
        }

        composable(Screen.Cart.route) {
            CartScreen()
        }
        composable(Screen.History.route) {
            HistoryScreen()
        }
        composable(Screen.Profile.route) {
            ProfileScreen()
        }
    }
}

This is my SplashScreen

@Composable
fun SplashScreen(navController: NavController) {

    LaunchedEffect(key1 = true,){
        delay(3000L)
        navController.navigate(Screen.BottomNavigation.route)
    }
    Scaffold {
        Text(
            "Splash Screen", style = MaterialTheme.typography.h4
        )
    }
}

This is my bottomNavScreen

var navItems = listOf<NavItem>(
    NavItem(label = "Home", route = "home_screen", icon = Icons.Default.Home),
    NavItem(label = "Search", route = "search_screen", icon = Icons.Default.Search),
    NavItem(label = "Cart", route = "cart_screen", icon = Icons.Default.ShoppingBag),
    NavItem(label = "History", route = "history_screen", icon = Icons.Default.Notes),
    NavItem(label = "Profile", route = "profile_screen", icon = Icons.Default.Person),

    )


@Composable
fun BottomNavScreen(navController: NavController) {
    val nnaa = rememberNavController()
    Scaffold(
        backgroundColor = Color.LightGray,
        bottomBar = {
            CustomBottomNavBar(items = navItems, navController = navController) {
                navController.navigate(it.route) {
                    popUpTo(navController.graph.findStartDestination().id) {
                        saveState = true
                    }
                    // Avoid multiple copies of the same destination when
                    // reselecting the same item
                    launchSingleTop = true
                    // Restore state when reselecting a previously selected item
                    restoreState = true
                }

            }
        }
    ) {
       //What to add here
        
    }
}
         

Upvotes: 2

Views: 1153

Answers (1)

Rakesh Verma
Rakesh Verma

Reputation: 806

I also faced the same issue, after splash screen I was not able to navigate using navcontroller. Instead of using multiple NavHost I fixed it by using the MutableStateFlow for selected bottomNavItem in Viewmodel for Main screen. Further screens navigation from Inner Views of MainScreen can be handled by using Nested Navigation graphs.

@Composable
fun MainScreen(vm: MainViewModel, navControllerRoot: NavHostController) {

val bottomBarItems = listOf(
    BottomBarItem.Home,
    BottomBarItem.Music,
    BottomBarItem.Movies,
    BottomBarItem.Profile,
)

val tabRouteState = vm.currentRouteFlow.collectAsState()

Scaffold(
    topBar = { ComposeTestTopBar() },
    bottomBar = {
        ComposeTestBottomBar(
            defaultSelected = BottomBarItem.Home,
            items = bottomBarItems,
            onItemTapped = { v -> vm.currentRoute.value = v.route })
    }
) {
    MainBody(tabRouteState.value)
  }
}

@Composable
fun MainBody(currentRoute: ComposeTestRoute) {
when (currentRoute.toString()) {
    ComposeTestRoute.HomeRoute.toString() -> HomeScreen(title = "HOME")
    ComposeTestRoute.MusicRoute.toString() -> MusicScreen(title = "MUSIC")
    ComposeTestRoute.MovieRoute.toString() -> MovieScreen(title = "MOVIES")
    ComposeTestRoute.ProfileRoute.toString() -> ProfileScreen(title = "PROFILE")
    else -> CircularProgressIndicator()
  }
}

@Composable
fun ComposeTestTopBar() {
TopAppBar(title = { Text(text = stringResource(R.string.app_name)) })
}

Upvotes: 1

Related Questions