Search code examples
kotlinandroid-studioandroid-jetpack-composenavigation-drawer

Jetpack Compose with Material 3: NavigationDrawer - add route to NavigationDrawerItem


im learning Jetpack Compose with Material 3. My Testapplication has a ModalNavigationDrawer now, which works fine. But the problem is, that every time, when im on the HomeScreen and i click the Icon for the HomeScreen, another instance of HomeScreen gets added to the backstack. I try to work with ModalDrawerSheet and NavigationDrawerItem. I know that i need to add a state variable to the NavigationDrawer, who holds the HomeRoute as default, and then override this variable if the user clicks on one of the NavDrawer icons. But i cant find a way how to give the NavigationDrawerItem the information, that it belongs to a certain route. Is there any chance to get everything done only with these components? Or do i have to make the Items myself from dataClass and pass them to Drawersheet?

Here is the part of the code:

     @Composable
     fun MainCompose() {
     val navController = rememberNavController()
     val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
     val items = listOf(Icons.Default.Favorite, Icons.Default.Face, Icons.Default.Email)
     val scope = rememberCoroutineScope()

     ***val currentScreen by remember(mutableStateOf("home")***


     ModalNavigationDrawer(
            drawerState = drawerState, gesturesEnabled = false,
            drawerContent = {

                ModalDrawerSheet(modifier = Modifier.fillMaxWidth(0.8f)) {
                        Spacer(modifier = Modifier.height(12.dp))


                        NavigationDrawerItem(icon = { Icon(items[0], contentDescription = null) },
                            label = { Text(text = "Home") },
                            selected = false,
                            onClick = {
                                        scope.launch { drawerState.close() }
                                        navController.navigate("home"){
                                            popUpTo("home")
                                        }})

i want to tell the NavigationDrawerItem that if currentScreen has the same value like the route of the icon, that the click should be ignored. I hope i could express what the problem is. Thank you.


Solution

  • You could use a LazyColumn and then use the items method to create all NavigationDrawerItems based on a List of Model classes.

    Create a model class with the information for each item:

    data class NavigationItemModel(
        val route: String,
        val icon: ImageVector,
        val label: @Composable () -> Unit,
    )
    

    Use the model classes to create NavigationDrawerItem:

    
    val navItems = listOf(
        NavigationItemModel("home", { Text("home") }, Icons.Default.Home),
        // insert other routes
    )
    
    val currentRoute by remember { mutableStateOf("home") }
    
    ...
    
    LazyColumn {
        items(navItems) { model ->
            NavigationDrawerItem(
                icon = { Icon(model.icon, contentDescription = null) },
                label = model.label,
                selected = (currentRoute == model.route),
                onClick = {
                    // Check if already on this route
                    if (currentRoute == model.route) {
                        return
                    }
                    scope.launch { drawerState.close() }
                    navController.navigate("home"){
                        popUpTo("home")
                    }
                    // Update current route
                    currentRoute = model.route
                }
            )
        }
    }