skip to Main Content

I’m building a mobile app with Jetpack Compose and would like to implement bottom navigation with multiple tabs. I have a DashboardCustomerScreen that includes a bottom navigation bar with icons and titles for "Home," "Reservation," and "Profile." I’m using a combination of Scaffold and custom components, and I have a working navigation setup using the Navigation component.

Here’s a snippet of the code for the DashboardCustomerScreen:

@Composable
fun DashboardCustomerScreen(profileCustomerViewModel: ProfileCustomerViewModel, dashboardViewModel: DashboardViewModel, navController: NavController) {
    // ... (other code)

    Scaffold(
        topBar = {
            // ... (top app bar)
        },
        bottomBar = {
            // ... (bottom navigation bar)
        },
        content = {
            // ... (content area)
        }
    )
}

I’m looking for guidance on refining the bottom navigation bar, handling item selection, and navigating to different destinations when a tab is selected. Are there any best practices or improvements I can make in terms of Jetpack Compose conventions?

2

Answers


  1. Chosen as BEST ANSWER

    Handle Item Selection:

    Utilize the NavHost for handling navigation between different destinations. It looks like you already have a NavHost set up in the SetupNavGraph function. Ensure that each screen is properly annotated with @Composable and connected to the NavHost.

    @RequiresApi(Build.VERSION_CODES.O)
    @Composable
    fun SetupNavGraph(
        navController: NavHostController
    ){
        NavHost(
            navController = navController,
            startDestination = Screen.Home.route
        ){
            composable(Screen.Home.route){
                Home(navController)
            }
            composable(Screen.DashboardCustomer.route){
                DashboardCustomerScreen(ProfileCustomerViewModel(LocalContext.current, DataManager(LocalContext.current)),
                    DashboardViewModel(DataManager(LocalContext.current)), navController)
            }
        }
    }
    
    sealed class Screen(val route: String) {
        object  Home : Screen("home")
        object DashboardCustomer : Screen("dashboardcustomer")
    }
    

    this is example of how i define bottom navigation

    data class BottomNavigationItem(
        val title: String,
        val selectedIcon: ImageVector,
        val unselectedIcon: ImageVector,
    )
    
    @RequiresApi(Build.VERSION_CODES.O)
    @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
    @Composable
    fun DashboardCustomerScreen(profileCustomerViewModel: ProfileCustomerViewModel, dashboardViewModel: DashboardViewModel, navController: NavController) {
        val items = listOf(
            BottomNavigationItem(
                title = "Home",
                selectedIcon = Icons.Filled.Home,
                unselectedIcon = Icons.Outlined.Home,
            ),
            BottomNavigationItem(
                title = "Reservation",
                selectedIcon = Icons.Filled.StickyNote2,
                unselectedIcon = Icons.Outlined.StickyNote2
            ),
            BottomNavigationItem(
                title = "Profile",
                selectedIcon = Icons.Filled.Person,
                unselectedIcon = Icons.Outlined.Person,
            )
        )
    
        var selectedItemIndex by rememberSaveable { mutableStateOf(0) }
        var expanded by remember {
            mutableStateOf(false)
        }
    
        val isSuccessful by dashboardViewModel.isSuccessful.observeAsState()
    
        if(isSuccessful == true){
            navController.navigate("login")
        }
    
        var openDialog by remember{ mutableStateOf(false) }
    
        if(openDialog){
            ChangePasswordDialog(dashboardViewModel = dashboardViewModel, setShowDialog = { openDialog = it }, navController = navController)
        }
    
            Scaffold(
                topBar = {
                    CenterAlignedTopAppBar(
                        colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
                            containerColor = MaterialTheme.colorScheme.primaryContainer,
                            titleContentColor = MaterialTheme.colorScheme.primary,
                        ),
                        title = {
                            Text(
                                "",
                                maxLines = 1,
                                overflow = TextOverflow.Ellipsis
                            )
                        },
                        actions = {
                            IconButton(onClick = { expanded = true }) {
                                Icon(
                                    imageVector = Icons.Filled.Menu,
                                    contentDescription = "Localized description"
                                )
                            }
                            DropdownMenu(
                                expanded = expanded,
                                onDismissRequest = { expanded = false },
                            ) {
                                DropdownMenuItem(
                                    text = {
                                        Text(text = "Change Password")
                                    },
                                    onClick = {
                                        expanded = false
                                        openDialog = true
                                    }
                                )
                                DropdownMenuItem(
                                    text = {
                                        Text(text = "Logout")
                                    },
                                    onClick = {
                                        expanded = false
                                        dashboardViewModel.logout()
                                    }
                                )
                            }
                        },
                    )
                },
                bottomBar = {
                    NavigationBar() {
                        items.forEachIndexed { index, item ->
                            NavigationBarItem(
                                selected = selectedItemIndex == index,
                                onClick = {
                                    selectedItemIndex = index
    //                                when (index) {
    //                                    0 -> navController.navigate("dashboard")
    //                                    1 -> navController.navigate("login")
    //                                }
                                },
                                label = {
                                    Text(text = item.title)
                                },
                                icon = {
                                    Icon(
                                        imageVector =
                                        if (selectedItemIndex == index)
                                            item.selectedIcon
                                        else item.unselectedIcon,
                                        contentDescription = item.title
                                    )
                                }
                            )
                        }
                    }
                },
                content = {
                        padding ->
                    Row(
                        Modifier
                            .fillMaxSize()
                            .padding(padding)
                            .consumeWindowInsets(padding)
                            .windowInsetsPadding(
                                WindowInsets.safeDrawing.only(
                                    WindowInsetsSides.Horizontal,
                                ),
                            ),
                    ) {
                        Column(Modifier.fillMaxSize()
                            )
                        {
                            when (selectedItemIndex) {
                                0 -> ReservationScreen(
                                    ReservationViewModel(
                                        DataManager(LocalContext.current)
                                    )
                                )
    
                                1 -> ReservasiScreen(
                                    ReservasiViewModel(
                                        LocalContext.current,
                                        DataManager(LocalContext.current)
                                    ),
                                    ReservasiUangJaminanViewModel(
                                        DataManager(LocalContext.current),
                                        LocalContext.current
                                    ),
                                    navController
                                )
    
                                2 -> ProfileCustomerScreen(profileCustomerViewModel, navController)
                            }
                        }
                    }
                }
            )
    
    }
    

  2. hi here just follow steps here
    and also check sample code project provided in Github it useful for you,

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search