Search code examples
androidkotlinandroid-jetpack-composeandroid-canvas

Individual Zoom for Canvas Rectangles


I'm trying to add zoom to the rectangles I drew with canvas, using rememberZoomState. However, when I zoom in one, it zooms in all of them, and the idea is to zoom them individually.

I know I could do something similar using pointerInput, but the idea is to use the library.

Is this possible?

My Code:

@Composable
internal fun ScreenShotDrawSpeech(
    bubbleDomain: BubbleDomain,
    modifier: Modifier = Modifier,
) {
    val textMeasurer = rememberTextMeasurer()
    val zoom = rememberZoomableState()

    Canvas(
        modifier = modifier
            .fillMaxSize()
            .background(background_overlay)
            .zoomable(zoom),
        onDraw = {
            bubbleDomain.predictions.forEach { prediction ->
                val left = prediction.x - prediction.width / 2
                val top = prediction.y - prediction.height / 2
                val right = left + prediction.width
                val bottom = top + prediction.height

                val rect = Rect(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())

                drawSpeechBoundingBox(text = prediction.confidence.toString(), boundingBox = rect, textMeasurer = textMeasurer)
            }
        },
    )
}

Solution

  • I think it is not possible to achieve this using rememberZoomState(). When you apply the zoomable Modifier to the Canvas, the whole Canvas is going to be transformed, not the individual contents drawn inside.
    You would need to apply the zoomable Modifier on each item drawn in the Canvas, which however is not possible as we have no Composables and no Composable scope in the onDraw function of the Canvas.

    If it is possible to replace the elements you draw in your Canvas with Composables, like a RectangleComposable, SpeechBubbleComposable, then you can draw these Composables into a Box and add the zoomable Modifier to each individual Composable.

    But if you need a Canvas, I think as you already said, you will have to use a pointerInput as described in this stackoverflow answer together with another mechanism to detect which item in the Canvas was selected.