I need to get data from the server and display it in the list Each item in the list can be selected with one click to display the button, but I cannot close it, I can only open it
this is item of list class
data class Task(
val deviceName: String,
val deviceId: String,
var selected :Boolean= Boolean,
)
this is data class
data class TaskStatus(
val taskList: SnapshotStateList<Task> = SnapshotStateList(),
val selectedNumber: Int = -1,
)
this is viewmodel class
private val _status = MutableStateFlow(TaskStatus())
val status = _status.asStateFlow()
fun getList(){
...
for(item in result){
_status.value.taskList.add(task)
}
}
fun selectTask(task: Task) {
val list = _status.value.taskList
val selectNumber = _status.value.selectedNumber
val newSelectNumber = list.indexOf(task)
if (newSelectNumber != selectNumber) {
if (selectNumber != -1) {
list[selectNumber].selected.value = false
}
}
task.selected.value = !task.selected.value
_status.update { it.copy(selectedNumber = newSelectNumber) }
}
this is Compose class
...
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.weight(1F),
verticalArrangement = Arrangement.spacedBy(11.dp), contentPadding = PaddingValues(16.dp)
) {
items(
taskStatus.taskList,
key = { it.deviceId }) { task ->
Item(task)
}
}
@Compose
fun Item(task:Task){
Column(){
Text(text = task.name)
Text(text = task.deviceId)
if(task.selected){
Botton()
}
}
}
I can only show but not hide Botton()
Look forward to and thank you in advance for your answer
CodePudding user response:
I can't compile your code so I tried to make my own implementation using the codes you provided, and I added a callback which will be triggered from your Task Item
Your TaskList
composable
@Composable
fun TaskList(
taskList: SnapshotStateList<Task>,
onSelected: (Task) -> Unit
) {
LazyColumn(
modifier = Modifier
.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(11.dp), contentPadding = PaddingValues(16.dp)
) {
items(
taskList,
key = { it.deviceId }) { task ->
Item(task) {
onSelected(it)
}
}
}
}
Your TaskItem
Composable
@Composable
fun Item(
task:Task,
onSelected: (Task) -> Unit
){
Column(
modifier = Modifier.clickable {
onSelected(task) // selection callback
}
){
Text(text = task.deviceName)
Text(text = task.deviceId)
if(task.selected) {
Box(modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.background(Color.Red)) {
}
}
}
}
And I mocked a VieModel
class TaskStateHolder {
private val _status = MutableStateFlow( TaskStatus (
taskList = mutableStateListOf(
Task(
deviceName = "Device 1",
deviceId = "Device 1 ID"
),
Task(
deviceName = "Device 2",
deviceId = "Device 2 ID"
),
Task(
deviceName = "Device 3",
deviceId = "Device 3 ID"
),
Task(
deviceName = "Device 4",
deviceId = "Device 4 ID"
),
)
))
val status = _status.asStateFlow()
fun selectTask(task: Task) {
_status.update {
val list = it.taskList
val newSelectNumber = list.indexOf(task)
val iterator = list.listIterator()
while (iterator.hasNext()) {
val obj = iterator.next()
if (task.deviceId == obj.deviceId) {
iterator.set(task.copy(selected = true))
} else {
iterator.set(obj.copy(selected = false))
}
}
it.copy(selectedNumber = newSelectNumber)
}
}
}
I modified your selectedTask function, executing _status flow
udpates in a single pass using the list's iterator.
Usage somewhere outside (e.g "TaskScreen")
val tasks by stateHolder.status.collectAsState()
Column {
TaskList(tasks.taskList) {
stateHolder.selectTask(it)
}
}