Reputation: 37733
Which whould be the best approach to display, for example, 2 types of dialogs on a screen and also parametrize the message to each dialog? For now I have a remember mutable state DialogType
enum
variable which represents if a dialog must be displayed or not, so if the state is MessageDialog
or ConfirmationDialog
will display one of those. But... what if I need to parametrize the message (or more variables like for example a image, but for this case it will be simplyfied to message) to one of these dialogs? Should I use another remember state variable with the string? If so, then I'm using two different remember state variables. Is that correct?
For sure there are complex ways to achieve this, creating special data classes, wrapping them, passing composable content as parameters to the dialog, etc... but I'm trying to avoid these kind of complex and overprogrammed developments and trying to find a simple and easy way to achieve this.
This is the sample code I did:
var dialogState by remember { mutableStateOf(DialogStateType.HIDDEN) }
var dialogMessage by remember { mutableStateOf("") }
In the buttons i change the state of these variables like this:
onClick = {
dialogMessage = "sample message text"
dialogState = DialogStateType.MESSAGE
}) {
onClick = {
dialogMessage = "sample confirmation dialog text"
dialogState = DialogStateType.CONFIRMATION
}) {
And in the main composable I display them using this:
when (dialogState) {
DialogStateType.MESSAGE -> {
MessageDialog(dialogMessage) {
dialogState = DialogStateType.HIDDEN
}
}
DialogStateType.CONFIRMATION -> {
ConfirmationDialog(dialogMessage,
{
CoroutineScope(Dispatchers.Default).launch {
//DO HARD JOB
}
},
{ dialogState = DialogStateType.HIDDEN },
{ dialogState = DialogStateType.HIDDEN })
}
DialogStateType.HIDDEN -> {}
}
This approach works and it's simple, but seems to be not too much escalable, Is this the recommended way of doing this? or is there a simpler and easier way?
Upvotes: 2
Views: 1092
Reputation: 1305
Kotlin's default arguments and ?.let {...}
can help
Some class representing state:
data class DialogState(val caption: String? = "Dialog",
val text: String? = null,
val imageResId: String? = null,
val confirmButtonText: String = "OK",
val cancelButtonText: String? = null,
val onConfirm: () -> Unit = {},
val onCancel: () -> Unit = {})
Generic dialog composabe like:
@Composable
fun GenericDialog(dialogState: DialogState, onDismiss: () -> Unit) {
Dialog(onDismissRequest = onDismiss) {
Surface {
Column(
modifier = Modifier.padding(10.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
dialogState.caption?.let {
Text(text = dialogState.caption,
style = TextStyle(fontWeight = FontWeight.ExtraBold))
Spacer(modifier = Modifier.size(10.dp))
}
dialogState.imageResId?.let{
//show image
Spacer(modifier = Modifier.size(10.dp))
}
dialogState.text?.let {
Text(text = dialogState.text)
Spacer(modifier = Modifier.size(10.dp))
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Button(onClick = dialogState.onConfirm) {
Text(text = dialogState.confirmButtonText)
}
dialogState.cancelButtonText?.let {
Spacer(modifier = Modifier.size(10.dp))
Button(onClick = dialogState.onCancel) {
Text(text = dialogState.cancelButtonText)
}
}
}
}
}
}
}
And then:
var showDialog by remember { mutableStateOf(false) }
var dialogState = remember { DialogState() }
//...
if (showDialog) GenericDialog(dialogState = dialogState) { showDialog = false }
//...
Button(onClick = {
dialogState = DialogState(caption = "Caption",
text = "Text text text text text text text text text text text",
onConfirm = {showDialog = false})
showDialog = true
}) {
Text(text = "Caption, text, one button")
}
// or
Button(onClick = {
dialogState = DialogState(caption = null,
text = "Text text text text text text text text text text text",
cancelButtonText = "Cancel",
onConfirm = {showDialog = false},
onCancel = {showDialog = false})
showDialog = true
}) {
Text(text = "Text, two buttons")
}
Upvotes: 1