Patroy
Patroy

Reputation: 377

How to draw some of the elements rotated on the Сanvas in Jetpack Compose?

I'm drawing chart in Jetpack Compose, with x labels written using drawIntoCanvas method. Basically very simple block of code:

data.forEachIndexed { index, point ->
    drawIntoCanvas {
        it.nativeCanvas.drawText(
            "${point.x}",
            chartCanvasStartX + index * intervalX,
            size.height + 4.dp.toPx(),
            textPaint
        )
    }
}

Output is as expected: enter image description here

However I would like to achieve those labels to be sloped at desired angle, to fit longer text. I've tried applying rotation to the canvas, but that produces output, where whole canvas is rotated, not the individual iterations of this forEach loop. Even using methods like canvas.save() and canvas.restore() between angle transformation didn't produce desired output. Maybe in Compose declarative world there is some simpler solution for drawing such a texts?

Here is mockup for visualization of what I would like to achieve: enter image description here

Note: Whole chart is written in single Compose Canvas method, because I want to have reference to every x value of chart to place label precisely at this point, so I don't want to place any Column with regular Compose Text with rotate modifier applied.

Upvotes: 2

Views: 4957

Answers (1)

Phil Dukhov
Phil Dukhov

Reputation: 87924

Generally using android.graphics.Canvas you can rotate the canvas before drawing the item, and then invert the rotation.

But also compose has a built-in solution for such cases: rotate will take effect only for the elements drawn inside the block:

Canvas(modifier = Modifier.fillMaxSize()) {
    val rect = Rect(Offset.Zero, size)
    drawLine(Color.Yellow, start = rect.topLeft, end = rect.bottomRight, strokeWidth = 20f)
    rotate(degrees = -45f, rect.center) {
        drawIntoCanvas { canvas ->
            canvas.nativeCanvas.drawText(
                "1",
                rect.center.x, rect.center.y,
                android.graphics.Paint().apply {
                    color = Color.Red.toArgb()
                    textSize = 100f
                }
            )
        }
    }
    drawLine(Color.Green.copy(alpha = 0.5f), start = rect.topRight, end = rect.bottomLeft, strokeWidth = 20f)
}

Result of my sample code (both before and after drawn lines are not rotated):

Upvotes: 4

Related Questions