MutableState 对象更改时文本和按钮颜色不更新

问题描述 投票:0回答:1

对于下面的代码,我试图让

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


                }

            }
        }
    }

}
android-jetpack-compose android-button mutablestateof
1个回答
0
投票

代码中的主要问题是您试图更改状态,而不是其内容。根据您的代码,我制作了一个轻型工作版本示例。此外,尝试查看 UDF(单向数据流) 方法,这将有助于理解如何使用 compose

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.collectAsState()

                Grid(selectedList) { color ->
                    processColor(color)
                }
            }
        }
    }

    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
                }
            }
        )
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.