1

I have this drawer:

val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
val items = listOf(Icons.Default.Favorite, Icons.Default.Face, Icons.Default.Email)
val selectedItem = remember { mutableStateOf(items[0]) }

ModalNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        items.forEach { item ->
            NavigationDrawerItem(
                icon = { Icon(item, contentDescription = null) },
                label = { Text(item.name) },
                selected = item == selectedItem.value,
                onClick = {
                    scope.launch { drawerState.close() }
                    selectedItem.value = item
                    //How to change the content of Scaffold's content section?
                },
                modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
            )
        }
    },
    content = {
        Scaffold(
            topBar = {
                //
            },
            content = { padding ->
                Text(
                    modifier = Modifier.padding(padding),
                    text = "Favorites"
                )
            }
        )
    }
)

Now, when I run the app, I get the correct TopBar and right under it a Text that holds the value of "Favorites". The problem is that I always want to have the same TopBar, and only change the Scaffold's content. So instead of "Favorites" I want to display "Face", when the second item is clicked.

I though to create some composable functions, to display the data, but I cannot call them from inside the onClick. Android Studio is complaining with:

@Composable invocations can only happen from the context of a @Composable function

I also thought on creating states and load that data according to that state. But isn't it so complicated to only display a single text?

In also thought on navigating to other screens but this means that each screen should have it own TopBar, which in my opinion requires adding more complexity to the app for no reason. I'm completely lost. How to solve this issue?

Joan P.
  • 2,368
  • 6
  • 30
  • 63

2 Answers2

1

You should just simply update a viewmodel state value in onclick and listen to that value inside your composable. When the value changes you can simply call other composable. It isn't that complex.

Arsh
  • 279
  • 2
  • 6
1

Creating a State to change content is not that complicated same goes for puting a NavHost composable inside your content block.

object Routes {
    const val Favorites = "Favorites"
    const val Faces = "Faces"
}

var route by remember {mutableStateOf(Routes.Favorites)}

ModalNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        items.forEach { item ->
            NavigationDrawerItem(
                icon = { Icon(item, contentDescription = null) },
                label = { Text(item.name) },
                selected = item == selectedItem.value,
                onClick = {
                    scope.launch { drawerState.close() }
                    selectedItem.value = item
                    // Change route
                    route = some new route...
                },
                modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
            )
        }
    },
    content = {
        Scaffold(
            topBar = {
                //
            },
            content = { padding ->
               if(route == Routes.Favorites) {
                  Text(
                    modifier = Modifier.padding(padding),
                    text = "Favorites"
                )
              }else {
                // other routes
              }
            }
        )
    }
)

With NavHost

    NavHost(
        navController = navController,
        startDestination = Routes.Favorites
    ) {
        composable(Routes.Favorites) {
            Favorites()
        }

        composable(Routes. Face) {
            Faces()
        }
    }
Thracian
  • 43,021
  • 16
  • 133
  • 222
  • Hey Thracian. Thanks for getting the time to answer my question. Yes, it turned out it wasn't so difficult to use states. And your solution on using routes, I will use in my next project. Thanks. Voted-up – Joan P. Aug 04 '22 at 10:16
  • Of course, it's simple. Routes are some made up properties i used for setting value of `State` to trigger recomposition and check new value on recomposition. You can have anything that is unique to your Composble or navigation – Thracian Aug 04 '22 at 12:52