公开的下拉菜单不会重新组合,直到我关闭下拉菜单

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

我有一个统计屏幕,使用下拉菜单来添加过滤器。例如,一个过滤器包含所有游戏类型,每个游戏旁边都有复选框。它最初填充了所有选中的框,因此所有游戏都包含在统计数据中。当用户取消选中游戏时,统计数据会更新,而不会更新未选中的游戏。一切都按我想要的方式工作,除了统计信息在我关闭下拉菜单之前不会显示更新的值。复选框在选中时会更新。我使用调试来查看统计信息在选中或取消选中复选框时更新。


val selectedGame = remember { SnapshotStateList<String>() }

ExposedDropdownMenuBox(
    expanded = expandedGame,
    onExpandedChange = { onExpandGameChange(it) },
) {

    ShowOutlinedTextField(
        readOnly = true,
        value = stringResource(id = R.string.game_filter),
        modifier = Modifier
            .padding(10.dp)
            .menuAnchor(type = MenuAnchorType.PrimaryNotEditable, 
             enabled = true)
    )

    ExposedDropdownMenu(
        expanded = expandedGame,
        onDismissRequest = { onExpandGameChange(false) }
    ) {
        gameNames.forEach { game ->
            DropdownMenuItem(
                onClick = { onExpandGameChange(false) },
                text = {
                    Row(
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Checkbox(
                            checked = 
                        selectedGame.contains(game.gameName),
                            onCheckedChange = { isChecked ->
                                if (isChecked) {
                                    selectedGame.add(game.gameName)
                                } else {
                                    selectedGame.remove(game.gameName)
                                }
                                
                         setSelectedGames(selectedGame.toList())
                            }
                        )
                        Spacer(modifier = Modifier.width(8.dp))
                        Text(text = game.gameName)
                    }
                }
            )
        }
    }
}

我尝试添加以下代码,但没有成功。

var forceRecomposition by remember { mutableStateOf(0) }

Checkbox(
    checked = selectedLocations.contains(casino.name),
    onCheckedChange = { isChecked ->
        if (isChecked) {
            selectedLocations.add(casino.name)
        } else {
            selectedLocations.remove(casino.name)
        }
        setSelectedCasinos(selectedLocations.toList())
        forceRecomposition++
    }
)
android kotlin android-jetpack-compose android-jetpack-compose-material3
1个回答
0
投票

您应该将

ExposedDropdownMenu
可组合项和您的统计可组合项所共有的状态提升到共同的父可组合项。然后,当用户单击
Checkbox

  • DropdownMenu 通知父 Composable 有关更改
  • 父可组合项更新所选项目的列表
  • 由于更新了列表,DropdownMenu 被重新组合
  • 统计 Composable 由于更新了 List 而被重新组合

请看下面的示例代码:

@Composable
fun MyComposableScreen() {
    val items = remember { arrayOf("Item A", "Item B", "Item C", "Item D") }
    val selectedItems = remember { mutableStateListOf(*items) }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.SpaceAround,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        MyDropdownMenu(
            allItems = items.toList(),
            selectedItems = selectedItems,
            addItem = { newItem ->
                selectedItems.add(newItem)
            },
            removeItem = { removedItem ->
                selectedItems.remove(removedItem)
            }
        )
        MyStatistics(selectedItems)
    }
}

MyDropdownMenu
可组合项如下所示:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyDropdownMenu(
    allItems: List<String>,
    selectedItems: List<String>,
    addItem: (String) -> Unit,
    removeItem: (String) -> Unit
) {

    var isExpanded by remember { mutableStateOf(false) }

    ExposedDropdownMenuBox(
        expanded = isExpanded,
        onExpandedChange = { isExpanded = it },
    ) {

        TextField(
            modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable),
            state = TextFieldState(selectedItems.joinToString(",")),
            readOnly = true,
            lineLimits = TextFieldLineLimits.SingleLine,
            label = { Text("Label") },
            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = isExpanded) },
            colors = ExposedDropdownMenuDefaults.textFieldColors(),
        )

        ExposedDropdownMenu(
            expanded = isExpanded,
            onDismissRequest = { isExpanded = false }
        ) {
            allItems.forEach { itemName: String ->
                DropdownMenuItem(
                    onClick = { /** do nothing or call addItem() / removeItem() **/ },
                    text = {
                        Row(
                            verticalAlignment = Alignment.CenterVertically
                        ) {
                            Checkbox(
                                checked = selectedItems.contains(itemName),
                                onCheckedChange = { isChecked ->
                                    if (isChecked) {
                                        addItem(itemName)
                                    } else {
                                        removeItem(itemName)
                                    }
                                }
                            )
                            Spacer(modifier = Modifier.width(8.dp))
                            Text(text = itemName)
                        }
                    }
                )
            }
        }
    }
}

最后,

MyStatistics
可组合项可能如下所示:

@Composable
fun MyStatistics(selectedItems: List<String>) {
    Text(
        "SELECTED ITEMS: \n${selectedItems.joinToString(",")}",
        fontSize = 24.sp
    )
}

请注意,最好使用

mutableStateListOf
而不是直接
remember
SnapshotStateList

输出:

Screen Recording

© www.soinside.com 2019 - 2024. All rights reserved.