LazyColumn 项目互斥
LazyColumn items mutual exclusive
假设我在 LazyColumn
中有一个项目列表,它们都可以被选中。我如何确保在选择一个项目时取消选择其他项目(因此一次只能选择 1 个项目)?
我在考虑 interactionSource
但我不太确定如何使用它。
我会将此逻辑提取到 ViewModel
中,您的项目是一个特定的 UIModel,其中包含项目的当前数据 + 它们的状态,其中包含 isSelected
状态。
例如:
data class YourUiModel(val id: Long, val isSelected: Boolean = false, ...)
private val _items = MutableStateFlow(emptyList<YourUiModel>())
val items: StateFlow<List<YourUiModel>>
get() = _items
private fun changeSelectionTo(uiModel: YourUiModel) {
_items.value = items.value.map { it.copy(isSelected = it.id == uiModel.id) }
}
...
您可以尝试使用 remember {...}
@Composable
fun MyComposeList(data: List<MyItemData>,...) {
val (selectedItem, setSelectedItem) = remember { mutableStateOf(null // or maybe data.first() } // remember current selected by state delegate
lazyColumn() { // your lazy column
items (data) { item -> // item = each item
// your compose item view
MyComposeItemView (
data = item, // pass data by each item
isSelected = data == selectedItem // set is item selected by default
) {
// on item click
setSelectedItem(it)
}
}
}
}
@Composable
fun MyComposeItemView(
data: MyItemData,
isSelected: Boolean,
onSelect: (MyItemData) -> Unit = {}) {
// here set item selected state = isSelected maybe change color or something
// assume we have box as single item
Box(Modifier.clickable {
onSelect(data) // cal on click function and pass current data as parameter
})
}
只需存储一个包含所选变量索引的变量
var sel by mutableStateOf(0)
现在,如果您要在可组合项中声明它,您可能想使用 remember here,但我强烈建议将其存储在视图模型中。一个简单的例子是
class VM: ViewModel(){
var sel by mutableStateOf(0) //Assuming 0 is selected initially, change it to -1 if you please
//Create a setter optionally, for state-hoisting
fun setSel(index: Int){
sel = index
}
}
在MainActivity中,
class MainActivity{
val vm by viewmodels<VM>()
setContent{
MySelectableList(
list = ...,
selected = vm.sel,
onSelectionChange = vm::setSel // Just pass the viewmodel if you did not create the setter
)
}
@Composable
fun MySelectableList(
list: List<Any>,
selected: Int,
onSelectionChange: (int) -> Unit // or vm, if you did not create the setter
){
list.forEachIndexed {index, item ->
// Now create this Composable yourself
ItemComposable(
isSelected = index == selected,
onClick = { onSelectionChange(index) } // Just focus and have a look at what's happening here
)
}
}
}
我这里使用的是状态提升,阅读this以供参考。如果您还没有参加此 Codelab,请务必参加
如果您之前将sel的初始值设置为-1,则需要进行额外的检查。完全理解这里流经的代码。
假设我在 LazyColumn
中有一个项目列表,它们都可以被选中。我如何确保在选择一个项目时取消选择其他项目(因此一次只能选择 1 个项目)?
我在考虑 interactionSource
但我不太确定如何使用它。
我会将此逻辑提取到 ViewModel
中,您的项目是一个特定的 UIModel,其中包含项目的当前数据 + 它们的状态,其中包含 isSelected
状态。
例如:
data class YourUiModel(val id: Long, val isSelected: Boolean = false, ...)
private val _items = MutableStateFlow(emptyList<YourUiModel>())
val items: StateFlow<List<YourUiModel>>
get() = _items
private fun changeSelectionTo(uiModel: YourUiModel) {
_items.value = items.value.map { it.copy(isSelected = it.id == uiModel.id) }
}
...
您可以尝试使用 remember {...}
@Composable
fun MyComposeList(data: List<MyItemData>,...) {
val (selectedItem, setSelectedItem) = remember { mutableStateOf(null // or maybe data.first() } // remember current selected by state delegate
lazyColumn() { // your lazy column
items (data) { item -> // item = each item
// your compose item view
MyComposeItemView (
data = item, // pass data by each item
isSelected = data == selectedItem // set is item selected by default
) {
// on item click
setSelectedItem(it)
}
}
}
}
@Composable
fun MyComposeItemView(
data: MyItemData,
isSelected: Boolean,
onSelect: (MyItemData) -> Unit = {}) {
// here set item selected state = isSelected maybe change color or something
// assume we have box as single item
Box(Modifier.clickable {
onSelect(data) // cal on click function and pass current data as parameter
})
}
只需存储一个包含所选变量索引的变量
var sel by mutableStateOf(0)
现在,如果您要在可组合项中声明它,您可能想使用 remember here,但我强烈建议将其存储在视图模型中。一个简单的例子是
class VM: ViewModel(){
var sel by mutableStateOf(0) //Assuming 0 is selected initially, change it to -1 if you please
//Create a setter optionally, for state-hoisting
fun setSel(index: Int){
sel = index
}
}
在MainActivity中,
class MainActivity{
val vm by viewmodels<VM>()
setContent{
MySelectableList(
list = ...,
selected = vm.sel,
onSelectionChange = vm::setSel // Just pass the viewmodel if you did not create the setter
)
}
@Composable
fun MySelectableList(
list: List<Any>,
selected: Int,
onSelectionChange: (int) -> Unit // or vm, if you did not create the setter
){
list.forEachIndexed {index, item ->
// Now create this Composable yourself
ItemComposable(
isSelected = index == selected,
onClick = { onSelectionChange(index) } // Just focus and have a look at what's happening here
)
}
}
}
我这里使用的是状态提升,阅读this以供参考。如果您还没有参加此 Codelab,请务必参加
如果您之前将sel的初始值设置为-1,则需要进行额外的检查。完全理解这里流经的代码。