How to combine FAB with BottomAppBar without overlapping nav items?

Viewed 708

I am using Material's BottomAppBar as my BottomNav in my Jetpack Compose's App. But when I tried to dock my fab on the BottomAppBar, it covers the nav items as the screenshot shows. Is there any way that could auto-add a space beside the fab?

Screenshot

I want to implement this effect without adding Space between nav items manually, like the effect below shows:

Desired effect

Below is my code:

@Composable
fun TestApp() {
    val navController = rememberNavController()

    Scaffold(
        bottomBar = {
            MyBottomAppBar(navController = navController)
        },
        floatingActionButton = {
            FloatingActionButton(onClick = { }) {
                Icon(imageVector = Icons.Rounded.Add, contentDescription = "fab")
            }
        },
        floatingActionButtonPosition = FabPosition.Center,
        isFloatingActionButtonDocked = true,
    ) {
        NavHost(navController, startDestination = Screen.Bill.route) {
            composable(Screen.Bill.route) { BillScreen() }
            composable(Screen.Chart.route) { ChartScreen() }
            composable(Screen.Budget.route) { BudgetScreen() }
            composable(Screen.Account.route) { AccountScreen() }
        }
    }
}
@Composable
fun MyBottomAppBar(navController: NavController) {
    BottomAppBar(
        cutoutShape = CircleShape
    ) {
        val navBackStackEntry by navController.currentBackStackEntryAsState()
        val currentRoute = navBackStackEntry?.arguments?.getString(KEY_ROUTE)

        Screen.items.forEachIndexed { index, screen ->
            BottomNavigationItem(               
                selected = (currentRoute == screen.route),
                icon = { Icon(screen.iconRes, screen.route) },
                label = { Text(stringResource(id = screen.labelRes)) },
                onClick = {
                    navController.navigate(screen.route) {
                        popUpTo = navController.graph.startDestination
                        launchSingleTop = true
                    }
                }
            )
        }
    }
}
1 Answers

The BottomNavigation is a Row and all the BottomNavigationItem are Box with the .weight(1f) modifier in the RowScope.

You can add an "empty" element in the middle of your Row or BottomNavigation with the same size of the BottomNavigationItem.

For example something like:

bottomBar = {
            BottomAppBar(cutoutShape = fabShape) {
                BottomNavigation {
                    items.forEachIndexed { index, item ->
                        if (index != 2){ // 
                        BottomNavigationItem(
                            // your implementation
                        )} else {
                            //Empty BottomNavigationItem
                            BottomNavigationItem(
                                icon = {},
                                label = {  },
                                selected = false,
                                onClick = {  },
                                enabled = false
                            )
                        }
                    }
                }

            }
        },

enter image description here

Related