Jetpack Compose: Is it possible to call an Composable function on a button click in another Composable function?

4.5k views Asked by At

When I tried to write text, on a buttonClick event, I ran into the problem, that I can't call a @Composable function inside another function because of the: @Composable invocations can only happen from the context of a @Composable function error. I tried to call the showResult function inside the Composable BeCalc function on a button click event. Any ideas? Thanks

@Composable
fun showResult(result: Int?) {
    Text(
        buildAnnotatedString {
            if(result != null && result != 0){
                append("Unnecessary Text")

                withStyle(style = SpanStyle(color = MaterialTheme.colors.primaryVariant))   //Einheiten-Anzahl in Farbe
                {
                    append("$result")
                }
                append("Unnecessary Text")
            }

        },
        modifier = Modifier.padding(top = 48.dp),
        fontSize = 20.sp,
        fontWeight = FontWeight.Bold
    )
}
@Composable
fun BeCalc(openDrawer: () -> Unit) {
var valueCarbohydrate by remember { mutableStateOf(TextFieldValue("")) }
var valueQuantity by remember { mutableStateOf(TextFieldValue("")) }
    var result: Int? = 0
        Button(
                modifier = Modifier.padding(top = 24.dp),
                colors = ButtonDefaults.buttonColors(MaterialTheme.colors.primaryVariant),

                onClick = {
                    val intValueQuantity = valueQuantity.text.toInt()
                    val intValueCarbohydrate = valueCarbohydrate.text.toInt()

                    if (intValueQuantity != null && intValueCarbohydrate != null) {

                        result = (intValueCarbohydrate / intValueQuantity)
                        showResult(result)


                    } else {
                        println("No value!")
                    }

                })Button(
                modifier = Modifier.padding(top = 24.dp),
                colors = ButtonDefaults.buttonColors(MaterialTheme.colors.primaryVariant),

                onClick = {
                    val intValueQuantity = valueQuantity.text.toInt()
                    val intValueCarbohydrate = valueCarbohydrate.text.toInt()

                    if (intValueQuantity != null && intValueCarbohydrate != null) {

                        result = (intValueCarbohydrate / intValueQuantity)
                        showResult(result)


                    } else {
                        println("No value!")
                    }

                }
    )
}
1

There are 1 answers

1
Gabriele Mariotti On BEST ANSWER

Compose doesn't work in this way.
You can't call a composable inside the onClick paramenter to display the updated value.
Instead you have to use a state and update it in the onClick.

Something like:

var count by rememberSaveable { mutableStateOf(0) }
var shouldShowResult by remember {
    mutableStateOf(false)
}

Button(
    //..
    onClick = {
        val intValueQuantity = valueQuantity.text.toInt()
        val intValueCarbohydrate = valueCarbohydrate.text.toInt()

        if (intValueQuantity != null && intValueCarbohydrate != null) {
            count = (intValueCarbohydrate / intValueQuantity)
            shouldShowResult = true
        } else {
            println("No value!")
        }
    }
){
    Text("Show Result")
}

if (shouldShowResult) {
    showResult(count)
}