Issue
I'm using a ListItem and I want to show an Alert Dialog when the user clicks on it. I've read that one approach is to create a value of mutableStateOf and then call the Composable inside of an if of the value, but this doesn't work.
Here is the code, I'm using Modifier.clickable because onClick doesn't exist on ListItem:
@ExperimentalMaterialApi
@Composable
fun UsersList() {
Column(modifier = Modifier
.fillMaxSize()
.background(elevation)) {
TopAppBar(
title = { Text("List of users") },
navigationIcon = {
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.ArrowBack, contentDescription = null)
}
},
backgroundColor = elevation2,
contentColor = Color.White
)
LazyColumn() {
item {
val openDialog = remember { mutableStateOf(true) }
ListItem(
text = { Text("Name", color = Color.White) },
icon = { Icon(Icons.Filled.Face, contentDescription = null, tint = Color.White) },
modifier = Modifier.clickable { if(openDialog.value) { OpenAlertDialog(openDialog)} },
)
}
}
}
}
@Composable
fun OpenAlertDialog(openDialog: MutableState<Boolean>) {
AlertDialog(
onDismissRequest = {
openDialog.value = false
},
title = {
Text(text = "Title")
},
text = {
Text(
"This area typically contains the supportive text " +
"which presents the details regarding the Dialog's purpose."
)
},
confirmButton = {
TextButton(
onClick = {
openDialog.value = false
}
) {
Text("Confirm")
}
},
dismissButton = {
TextButton(
onClick = {
openDialog.value = false
}
) {
Text("Dismiss")
}
}
)
}
Solution
You shouldn't be calling Composables from a callback. Instead put the composable along with other composable function calls surrounded by an if statement. Something like this:
val openDialog = remember { mutableStateOf(false) } // Set initial value to false so that dialog is not displayed initially
LazyColumn {
item {
ListItem(
text = { Text("Name", color = Color.White) },
icon = { Icon(Icons.Filled.Face, contentDescription = null, tint = Color.White) },
modifier = Modifier.clickable { openDialog.value = true },
)
}
}
if(openDialog.value) {
OpenAlertDialog(openDialog)
}
This should work.
One thing I would like to add is that instead of passing the openDialog state directly down the hierarchy, pass a lambda which updates the state. This will decouple the implementation of OpenAlertDialog() composable from the caller and increase its reusability (like if you want to perform some other operations when the dialog is dismissed, you could do that then).
Like this:
fun OpenAlertDialog(onDismiss(): () -> Unit) {
AlertDialog(
onDismissRequest = onDismiss,
... // Similarly for confirm and dismiss button onClick lambdas
)
}
And in the caller function, use
if(openDialog.value) {
OpenAlertDialog { openDialog.value = false }
}
Answered By - Arpit Shukla
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.