I have a layout where each item in a LazyColumn
can display an item-specific dialog. The Dialogs
showed and worked fine except for some of the larger ones where whenever I would try to edit text in one of the dialog's TextFields
it would trigger the dialog to disappear.
I tried a lot of different approaches and the weirdest thing was that the dialog works fine and allows me do edit the textfields if I only scroll the LazyColumn
by even 1 item before attempting to show the dialog.
It has proven hard to reproduce the issue in a simple setting as changing even basic elements of my code makes the bug disappear but I finally managed. The appearance of the bug seems to depend on the LazyColumn
being Scrollable
and on the KeyBoard to be of type text. Next a somewhat long code sample and a GIF showing the issue:
@Composable
fun JointCourseTemplate(courseTemplateDto: CourseTemplateDto) {
LazyColumn(
//state= LazyListState()
){
for(i in 0..4){
item { TestPart(i = i) }
for (j in 0..8){
item { TestItem(i = j) }
}
}
}
}
@Composable
fun TestPart(i:Int) {
var showDialog by remember {
mutableStateOf(false)
}
Row(Modifier.padding(8.dp)) {
Text("part"+i)
Button(onClick = { showDialog=true }) {
Text("show dialog")
}
}
PartDialog(showDialog = showDialog, hideDialog = {showDialog=false})
}
@Composable
fun TestItem(i:Int) {
Row(Modifier.padding(8.dp)) {
Text("item"+i)
Button(onClick = { /*TODO*/ }) {
Text("show dialog")
}
}
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PartDialog(showDialog:Boolean, hideDialog: () -> Unit) {
var text by remember {
mutableStateOf("")
}
if (showDialog) {
Dialog(properties = DialogProperties(
dismissOnClickOutside = false,
usePlatformDefaultWidth = false
),
onDismissRequest = { hideDialog() }) {
Surface(
modifier = Modifier
//.wrapContentHeight()
//.fillMaxWidth(0.9f)
.width(400.dp)
.height(600.dp),
shape = RoundedCornerShape(10.dp)
) {
Column {
Text(text = "Some Dialog")
OutlinedTextField(value = text, onValueChange = {text=it}, label = { Text(text = "TroubleMaker")})
}
}
}
}
}
This problem is due to the fact that you open the dialog from a lazy cell, which is located at the bottom of the screen. Therefore, when the keyboard appears, this cell becomes invisible and is removed from the view tree. I would say this is intended behavior.
I would suggest that you move the dialog from LazyColumn
. Perhaps you need information about a particular item to be displayed inside the dialog, you can store the selected item instead of a boolean value:
val (selectedDialogItem, setSelectedItem) = remember { mutableStateOf<Int?>(null) }
LazyColumn {
items(4) { i ->
Row(Modifier.padding(8.dp)) {
Text("part"+i)
Button(onClick = {
setSelectedItem(i)
}) {
Text("show dialog")
}
}
}
}
if (selectedDialogItem != null) {
Dialog(
// ...
)
}
p.s. I'm not using delegation here to allow selectedDialogItem
smart cast inside if
block