Цвет текста и кнопки не обновляется при изменении объекта MutableState

Для приведенного ниже кода я пытаюсь обновить selectedColorsText всякий раз, когда пользователь нажимает кнопку. После выбора фон кнопки должен стать черным, а текст внутри него — белым. Если флажок снят, кнопка должна снова стать белой, а текст внутри нее — черным. Однако ни selectedColorsText, ни цвета кнопок не обновляются должным образом. Что я делаю не так?

enum class ColorsEnum(val rawValue: String) {
    red("Red"),
    orange("Orange"),
    yellow("Yellow"),
    green("Green"),
    blue("Blue")

}


@Composable
fun LazyGridView() {

    var selectedColors by remember { mutableStateOf(arrayListOf<String>()) }
    var selectedColorsText by remember { mutableStateOf("") }

    Column (
        verticalArrangement = Arrangement.spacedBy(10.dp)
    )
    {

        Text("Selected Colors: $selectedColorsText")


        LazyVerticalGrid(
            columns = GridCells.Fixed(2),
            verticalArrangement = Arrangement.spacedBy(10.dp),
            horizontalArrangement = Arrangement.spacedBy(10.dp)
        ) {
            items(ColorsEnum.values()) { color ->

                Button(
                    onClick = {
                        if (selectedColors.contains(color.rawValue)) {
                            selectedColors.remove(color.rawValue)
                            selectedColorsText = selectedColors.joinToString(", ")

                            Log.d("selectedColors = ", "$selectedColors")
                            Log.d("selectedColorsText = ", "$selectedColorsText")

                        } else {
                            selectedColors.add(color.rawValue)

                            selectedColors.sortBy { colorName ->
                                ColorsEnum.values()
                                    .find { it.rawValue == colorName }
                                    ?.let(ColorsEnum.values()::indexOf)
                            }

                            Log.d("selectedColors = ", "$selectedColors")
                            Log.d("selectedColorsText = ", "$selectedColorsText")

                        }
                    },
                    modifier = Modifier
                        .border(
                            width = 1.dp,
                            color = Color.Black,
                            shape = RoundedCornerShape(5.dp)
                        ),
                    colors = ButtonDefaults.buttonColors(
                        backgroundColor =
                        if (isSystemInDarkTheme()) {
                            if (selectedColors.contains(color.rawValue)) {
                                Color.White
                            } else {
                                Color.Black
                            }
                        } else {
                            if (selectedColors.contains(color.rawValue)) {
                                Color.Black
                            } else {
                                Color.White
                            }
                        }
                    ),

                    ) {

                    Text(
                        text = color.rawValue,
                        style = TextStyle(
                            fontWeight = FontWeight.Bold,
                            color =
                            if (isSystemInDarkTheme()) {
                                if (selectedColors.contains(color.rawValue)) {
                                    Color.Black
                                } else {
                                    Color.White
                                }
                            } else {
                                if (selectedColors.contains(color.rawValue)) {
                                    Color.White
                                } else {
                                    Color.Black
                                }
                            }
                        ),
                    )


                }

            }
        }
    }

}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Основная проблема в вашем коде в том, что вы пытаетесь изменить состояние, а не его содержимое. Из вашего кода я сделал простой пример. Кроме того, попробуйте взглянуть на подход UDF (Unidirectional Data Flow), он очень поможет в понимании того, как работать с композицией.

class MainActivity : ComponentActivity() {

    // Create flow in ViewModel layer
    private val _selectedColors = MutableStateFlow<List<ColorsEnum>>(listOf())
    val selectedColors: StateFlow<List<ColorsEnum>> = _selectedColors

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TestApplicationTheme {

                // Subscribe on "selectedColors" flow in compose layer
                val selectedList by selectedColors.collectAsStateWithLifecycle()

                Grid(selectedList, ::processColor)
            }
        }
    }

    private fun processColor(color: ColorsEnum) {
        // update selected colors in ViewModel layer
        _selectedColors.update { selected ->
            if (selected.contains(color)) {
                selected - color
            } else {
                selected + color
            }
        }
    }
}

enum class ColorsEnum(val rawValue: String) {
    RED("Red"),
    ORANGE("Orange"),
    YELLOW("Yellow"),
    GREEN("Green"),
    BLUE("Blue")
}

@Composable
private fun Grid(selectedColors: List<ColorsEnum>, onClick: (ColorsEnum) -> Unit) {
    LazyVerticalGrid(
        columns = GridCells.Fixed(2),
        verticalArrangement = Arrangement.spacedBy(10.dp),
        horizontalArrangement = Arrangement.spacedBy(10.dp)
    ) {
        items(ColorsEnum.values()) { color ->

            GridItem(
                color = color,
                isChecked = selectedColors.contains(color),
                // also look on command pattern for process different 
                // kinds callback and data from your UI
                onClick = onClick
            )
        }
    }
}

@Composable
private fun GridItem(
    color: ColorsEnum,
    isChecked: Boolean,
    onClick: (ColorsEnum) -> Unit
) {
    Button(
        modifier = Modifier
            .border(
                width = 1.dp,
                color = Color.Black,
                shape = RoundedCornerShape(5.dp)
            ),
        colors = ButtonDefaults.buttonColors(
            backgroundColor =
            if (isSystemInDarkTheme()) {
                if (isChecked) {
                    Color.White
                } else {
                    Color.Black
                }
            } else {
                if (isChecked) {
                    Color.Black
                } else {
                    Color.White
                }
            }
        ),
        onClick = {
            onClick.invoke(color)
        },
    ) {
        Text(
            text = color.rawValue,
            color = if (isSystemInDarkTheme()) {
                if (isChecked) {
                    Color.Black
                } else {
                    Color.White
                }
            } else {
                if (isChecked) {
                    Color.White
                } else {
                    Color.Black
                }
            }
        )
    }
}

В моем коде цвета были отсортированы по порядку перечисления. Как я могу сделать это в этом коде сейчас в функции processColor?

Vaz 13.05.2023 21:04

@Vaz Для этого вам нужно создать собственное объявление, некоторый класс, который содержит ваше значение перечисления и состояние (отметить/снять отметку), и предоставить этот объект вместо перечисления в пользовательском интерфейсе.

Nuclominus 15.05.2023 16:10

Другие вопросы по теме

Похожие вопросы

Бинарная версия его метаданных — 1.7.1, ожидаемая версия — 1.5.1. ПРОБЛЕМА С КОМНАТОЙ
Почему в Android Studio Flamingo не найдено пустое действие создания сообщения | 2022.2.1
Как исправить эффект пульсации по умолчанию при изменении цвета кнопок в Compose?
Проблема: рекомпозиция не происходит, когда я меняю состояние пользовательского интерфейса (2d LIST) в компоновке реактивного ранца Android
ModalBottomSheetLayout снова не открывается при создании реактивного ранца
Как лучше всего хранить большие объемы текстовых данных для элементов lazycolumn?
Дублирующаяся ошибка класса при добавлении зависимостей от MVVM Jetpack Compose
Jetpack Compose не выполняет предварительный просмотр, если в композиции есть компонуемый текст
Форма создания Android Jetpack с управлением состоянием класса
Вызовы @composable могут происходить только из контекста функции @composable для Composable с LaunchedEffect и AndroidViewBinding