I was developing an app where I'm using Jetpack Compose as UI developing tool, and I design some kind of custom AlertDialog, which is the following:
CustomAlertDialog.kt
@Composable
fun SimpleAlertDialog(
hero: CharacterModel? = null,
show: Boolean,
onConfirm: () -> Unit,
onDismiss: () -> Unit,
textDescription: String,
textTittle: String,
) {
if(show){
AlertDialog(
onDismissRequest = onDismiss,
confirmButton = {
TextButton(onClick = onConfirm)
{ Text(text = "OK") }
},
dismissButton = {
TextButton(onClick = onDismiss)
{ Text(text = "Cancel") }
},
title = { Text(text = textTittle) },
text = { Text(text = textDescription) }
)
}
}
But when I try to use in a detailScreen, I get the following context Composable error:
@Composable invocations can only happen from the context of a @Composable function
the region of code where I try to instances the following, where I get the error:
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MyCharactersListRowView(
viewmodel: MainViewModel,
characterModel: CharacterModel,
popBack: () -> Unit
) {
val (characterSelected, setCharacterSelected) = remember { mutableStateOf<CharacterModel?>(null) } //HOOK FUNCTION
val openDialog = remember { mutableStateOf(false) }
Row(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = { setCharacterSelected(characterModel) })
.padding(vertical = 8.dp, horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically
){
AsyncImage(
model = characterModel.image,
contentDescription = characterModel.name,
contentScale = ContentScale.Fit,
modifier = Modifier
.size(60.dp)
.clip(CircleShape)
.combinedClickable(
onLongClick = {
if (characterSelected != null) {
SimpleAlertDialog(
hero = characterSelected,
show = true,
onConfirm = {
viewmodel
.deleteCharacter(characterSelected!!.id.toLong())
.also {
Log.d(
"info",
"rowAffected: ${viewmodel.rowAffected.value}"
)
if (viewmodel.rowAffected.value.toInt() != 0) {
Toast
.makeText(
LocalContext.current!!,
"¡ ${characterSelected.name} bought sucessfully!",
Toast.LENGTH_LONG
)
.show()
.also {
openDialog.value = false
}
} else {
Toast
.makeText(
LocalContext.current!!,
viewmodel.loadError.value,
Toast.LENGTH_LONG
)
.show()
.also {
openDialog.value = false
}
}
}
},
onDismiss = { openDialog.value = false },
textTittle = "Remove character",
textDescription = "Would you like to remove ${characterSelected.name} from your characters?"
)
} else {
}
},
onClick = {
//TODO {Do something}
}
)
)
...
...
So I know is a quite beginner error, but I've not been able to get into a working solution, due to take thanks in advance is you know how implement it.
CodePudding user response:
You can't call a Dialog from a lambda that doesn't have @Composable annotation. You can check this answer out for differences between Composable and non-Composable functions.
fun Modifier.combinedClickable(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onLongClickLabel: String? = null,
onLongClick: (() -> Unit)? = null,
onDoubleClick: (() -> Unit)? = null,
onClick: () -> Unit
)
These lambdas are not @Composable
Common way for showing dialog in Jetpack Compose is
var showDialog by remember {mutableStateOf(false)}
if(characterSelected && showDialog) {
SimpleAlertDialog(onDismiss={showDialog = false})
}
and change showDialog to true inside long click
onLongClick = {
showDialog = true
}