Как изменить содержимое внутри Scaffold, которое существует внутри ящика в Jetpack Compose?

У меня есть этот ящик:

      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"
                )
            }
        )
    }
)

Теперь, когда я запускаю приложение, я получаю правильный TopBar и прямо под ним текст, который содержит значение «Избранное». Проблема в том, что я всегда хочу иметь один и тот же TopBar и менять только содержимое Scaffold. Поэтому вместо «Избранное» я хочу отображать «Лицо» при нажатии второго элемента.

Я хотел создать некоторые составные функции для отображения данных, но я не могу вызывать их изнутри onClick. Android Studio жалуется на:

Вызовы @Composable могут происходить только из контекста функции @Composable.

Я также думал о создании состояний и загрузке этих данных в соответствии с этим состоянием. Но не так ли сложно отображать только один текст?

Мы также думали о переходе на другие экраны, но это означает, что каждый экран должен иметь свой собственный TopBar, что, на мой взгляд, требует усложнения приложения без всякой причины. Я полностью потерян. Как решить эту проблему?

2 ответа

Вы должны просто обновить значение состояния модели представления в onclick и прослушать это значение внутри вашего компонуемого. Когда значение изменяется, вы можете просто вызвать другой компонуемый. Это не так сложно.

Создание состояния для изменения контента не так сложно, как и размещение компонуемого NavHost внутри вашего блока контента.

      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
              }
            }
        )
    }
)

С NavHost

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

        composable(Routes. Face) {
            Faces()
        }
    }