How to hide bottom navigation bar while scrolling down and show it while scrolling up in jetpack compose?

Viewed 897

I'm creating a simple app with bottom navigation bar. I want to hide bottom navigation bar while scrolling down and show it while scrolling up in a composable screen.

Any help would be appreciated. Please do let me know if you need any more code. I have attached all the code that I think are relevant to this problem.

This is my bottom navigation bar.

@Composable
fun BottomBar(navController: NavController) {

    val items = listOf(
        NavigationItem.Home,
        NavigationItem.Search
    )

    BottomNavigation(
        backgroundColor = MaterialTheme.colors.DarkRed,
        contentColor = Color.White
    ) {

        val navBackStackEntry by navController.currentBackStackEntryAsState()
        val currentRoute = navBackStackEntry?.destination?.route

        items.forEach { item ->
            BottomNavigationItem(
                selected = currentRoute == item.route,
                icon = {
                    Icon(
                        imageVector = item.icon,
                        contentDescription = "Icon",
                        modifier = Modifier.size(28.dp)

                    )
                },
                alwaysShowLabel = false,
                selectedContentColor = Color.White,
                unselectedContentColor = Color.White.copy(0.4f),
                onClick = {
                    navController.navigate(item.route){
                        // Pop up to the start destination of the graph to
                        // avoid building up a large stack of destinations
                        // on the back stack as users select items
                        navController.graph.startDestinationRoute?.let{route ->
                            popUpTo(route){
                                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
                    }

                }
            )
        }
    }
}

This is my Main Screen

@Composable
fun MainScreen(){

    val navController = rememberNavController()

    Scaffold(topBar = {
        ActionBar("Books")
    },
        bottomBar = {
            BottomBar(navController)
        }){

        NavigationGraph(navController = navController)
    }
}

And this NavigationGraph

@Composable
fun NavigationGraph(navController: NavHostController){

    NavHost(navController = navController, startDestination = NavigationItem.Home.route ){

        composable(NavigationItem.Home.route){
            HomeScreen()
        }
        composable(NavigationItem.Search.route){
            SearchScreen()
        }
    }
}
1 Answers

You can use a LazyListState to track the state of the list and only show the BottomBar when the scrollState index is initial. This can be done by:

For LazyColumn:

@Composable
fun HomeScreen(scrollState: LazyListState) {

    LazyColumn(
        state = scrollState,
    ) {
        ...
      }
}

For NavigationGraph:

@Composable
fun NavigationGraph(navController: NavHostController, scrollState: LazyListState){

    NavHost(navController = navController, startDestination = NavigationItem.Home.route ){

        composable(NavigationItem.Home.route){
            HomeScreen(scrollState = scrollState)
        }
        composable(NavigationItem.Search.route){
            SearchScreen()
        }
    }
}

In the MainScreen:

@Composable
fun MainScreen(){

    val navController = rememberNavController()
    val scrollState = rememberLazyListState()

    Scaffold(topBar = {
        ActionBar("Books")
    },
        bottomBar = {
         if(scrollState.firstVisibleItemIndex == 0){ 
                  BottomBar(navController) 
           }
           
        }){

        NavigationGraph(navController = navController, scrollState = scrollState)
    }
}

This way the BottomBar will only show up when the list is at top.

Related