Search code examples
androidkotlinandroid-jetpack-composeandroid-buttonandroid-compose-button

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


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!")
                    }

                }
    )
}

Solution

  • 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)
    }