8

I'm getting data from the server and displaying it in the list, each item 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, ) 

My ViewModel

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

My LazyColumn

... 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 the button

Thank you in advance.

1 Answer 1

1

I can't compile your code directly so I tried to make my own implementation. 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) } } 

enter image description here

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your answer. I've tried your method, but I'm sorry I didn't make it clear. I mean, the data has changed but the display has not changed. I can't even use your method. I can expand every item, but if you want to expand one of them, the other will be closed
I want to open only one item at a time
I tried my own implementation using the available codes you posted, please see the updated answer and the .gif showing single selection
Thank you very much for your answer. I have completed the functions I need and optimized the code you gave me. I will selectedNumber -> selectId
thanks again,I have some small problems How long will the data of the viewmodel remain? If two identical viewmodels are created, will the data be the same? Maybe I should send another question

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.