androidkotlinandroid-jetpack-composeandroid-canvasandroid-jetpack

How to invoke @Composable function from DrawScope in Jetpack Compose?


I draw bar chart. I want to draw at the end of list loading bar with animation(as a separate function) but I cant invoke @Composable function. Error:

@Composable invocations can only happen from the context of a @Composable function

@Composable
fun Chart(
    modifier: Modifier = Modifier,
    model: BarData
) {
    Column(modifier = modifier) {
        Canvas(
            modifier = Modifier
                .weight(1f)
                .fillMaxWidth()
            
        ) {
            val radius = 45f
            
            val (paidBarHeight, incomingBarHeight) = computeBarsHeights(
                paidRatioAnim,
                incomingRatioAnim,
                size
            )

            if(!model.isLoading) {
                rotate(180f, pivot = size.center) {
                    drawRoundRect(
                        color = ChartBackgroundGreyColor,
                        size = size.copy(height = incomingBarHeight),
                        cornerRadius = CornerRadius(radius, radius)
                    )
                    drawRoundRect(
                        color = ChartBasicGreenColor,
                        size = size.copy(height = paidBarHeight),
                        cornerRadius = CornerRadius(radius, radius)
                    )
                }
            } else {
                //HOW TO DRAW LOADING BAR
            }
        }
    

} }


Solution

  • As you've seen, a Canvas composable doesn't allow you to draw in it directly. It's similar to a LazyColumn in that regard. You'll need to use the DrawScope methods to draw the content you want.

    In this case, you should draw your loading bar outside the Canvas:

        Column(modifier = modifier) {
            if (model.isLoading) {
                // draw loader
            } else
               Canvas(...)
            }
        }