Nikola C
Nikola C

Reputation: 362

Jetpack Compose Canvas drawing order issue

This problem is regarding Z-Axes of elements inside Canvas in Jetpack Compose. I have troubles to figure out how to stack elements. I know they stack one over other as they are being drawn, like in example below:

Canvas(modifier = Modifier.fillMaxWidth().padding(20.dp)) {
    val radius1 = 30f * dpi
    val radius2 = 20f * dpi
    val yStart = size.height.div(2)
    val xStart = size.width.div(2)
    drawCircle(
        color = Color.Red,
        center = Offset(
            x = xStart,
            y = yStart
        ),
        radius = radius1
    )
    drawCircle(
        color = Color.Green,
        center = Offset(
            x = xStart,
            y = yStart
        ),
        radius = radius2
    )
}

So we get this result: enter image description here

In the next step I get an event in my code that needs to move green circle behind red circle. enter image description here

NOTE: I know I can just make a method to replace order of what circle is being draw first with some if statement. But my real life example is very complex with a lot of different draw composable interacting.

Is there a way to set some kind of elevation for every drawCircle so I can stack them in app runtime, depending of my final code result?

Upvotes: 2

Views: 1737

Answers (1)

Phil Dukhov
Phil Dukhov

Reputation: 88024

I can think of two ways to do it:

  1. You can create a enum for each item. Generically it can be any information which can be placed in a list - enum, data class, etc:

    enum class CanvasItem {
        RedCircle,
        GreenCircle,
    }
    
    val canvasItems = listOf(
        CanvasItem.GreenCircle,
        CanvasItem.RedCircle,
    )
    Canvas(modifier = Modifier) {
        canvasItems.forEach {
            when (it) {
                CanvasItem.GreenCircle -> {
                    drawCircle(
                        color = Color.Green,
                        // ...
                    )
                }
                CanvasItem.RedCircle -> {
                    drawCircle(
                        color = Color.Red,
                        // ...
                    )
                }
            }
        }
    }
    
  2. Drawing each figure in a separate Canvas, placing all of them in a Box and applying Modifier.zIndex to control order:

    Box {
        val modifier = Modifier.fillMaxWidth().padding(20.dp)
        Canvas(
            modifier = modifier
                .zIndex(2f)
        ) {
            drawCircle(
                color = Color.Green,
                // ...
            )
        }
        Canvas(
            modifier = modifier
                .zIndex(1f)
        ) {
            drawCircle(
                color = Color.Green,
                // ...
            )
            drawCircle(
                color = Color.Red,
                // ...
            )
        }
    }
    

Upvotes: 4

Related Questions