单选 - 惰性列中的取消选择

Nam*_*man 6 android kotlin android-jetpack android-jetpack-compose lazycolumn

问题::: 我想创建一个惰性列,一次只能选择或取消选择一个选项。现在,每当我单击惰性列内的行组件时,所有行都会被选中。

代码 :::

@Composable
fun LazyColumnWithSelection() {

    var isSelected by remember {
        mutableStateOf(false)
    }
    
    var selectedIndex by remember { mutableStateOf(0) }
    
    val onItemClick = { index: Int -> selectedIndex = index }

    LazyColumn(
        modifier = Modifier.fillMaxSize(),
    ) {
        items(100) { index ->

            Row(modifier = Modifier
                .fillMaxWidth()
                .clickable {
                    onItemClick.invoke(index)
                    if (selectedIndex == index) {
                        isSelected = !isSelected
                    }
                }
                .padding(16.dp),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically) {
                Text(text = "Item $index", modifier = Modifier.padding(12.dp), color = Color.White)
                if (isSelected) {
                    Icon(imageVector = Icons.Default.Check,
                        contentDescription = "Selected",
                        tint = Color.Green,
                        modifier = Modifier.size(20.dp))
                }
            }

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当前结果:::

点击之前->

点击之前

点击后->

点击后

您可以看到所有项目都被选中,但我应该能够一次选择或取消选择一项,而不是全部。

我尝试使用记住状态进行选择,但我认为我在索引选择或 if 语句中做错了一些事情。

z.g*_*g.y 7

这可能会给你一个良好的开端。

所以我们这里有4组件:

  • 数据类
  • 阶级状态持有者
  • 可组合项目
  • 可组合项目列表

ItemData

  data class ItemData(
      val id : Int,
      val display: String,
      val isSelected: Boolean = false
  )
Run Code Online (Sandbox Code Playgroud)

State holder

class ItemDataState {

    val itemDataList = mutableStateListOf(
        ItemData(1, "Item 1"),
        ItemData(2, "Item 2"),
        ItemData(3, "Item 3"),
        ItemData(4, "Item 4"),
        ItemData(5, "Item 5")
    )

    // were updating the entire list in a single pass using its iterator
    fun onItemSelected(selectedItemData: ItemData) {
        val iterator = itemDataList.listIterator()

        while (iterator.hasNext()) {
            val listItem = iterator.next()

            iterator.set(
                if (listItem.id == selectedItemData.id) {
                    selectedItemData
                } else {
                    listItem.copy(isSelected = false)
                }
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Item Composable

@Composable
fun ItemDisplay(
    itemData: ItemData,
    onCheckChanged: (ItemData) -> Unit
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .height(80.dp)
            .border(BorderStroke(Dp.Hairline, Color.Gray)),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {

        Text(text = if (itemData.isSelected) "I'm selected!" else itemData.display)

        Checkbox(
            checked = itemData.isSelected,
            onCheckedChange = {
                onCheckChanged(itemData.copy(isSelected = !itemData.isSelected))
            }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

最后是ItemList( LazyColumn)

@Composable
fun ItemList() {

    val itemDataState = remember { ItemDataState() }

    LazyColumn {
        items(itemDataState.itemDataList, key = { it.id } ) { item ->
            ItemDisplay(
                itemData = item,
                onCheckChanged = itemDataState::onItemSelected
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所有这些都是可复制和粘贴的,因此您可以快速运行。这些代码应该足够简单,以便您可以轻松地剖析它们并将它们用作您自己的用例的参考。

请注意,我们在这里使用的数据类具有id唯一的属性,并且我们将其用作 的key参数LazyColumn's item

我通常使用唯一标识符来实现 UI 集合组件,以避免潜在的麻烦,例如 UI 显示/删除/回收错误的项目。

在此输入图像描述