androidandroid-jetpack-compose

Android Jetpack Compose: how to zoom a image in a "box"?


I am going to build a zoomable image view inside a box, like the first screenshot. But when I zoom in on the image, it will go out of the box. Is there a way to zoom the image, but keep the size? Without view or fragment, only box seems not enough. I am expecting the image to get bigger, but still stay inside the red box, but I got the second screenshot after zooming in.

Before zoom in After zoom in

Thanks to nglauber and Amirhosein, I got the final solution with having the zooming and dragging features at the same time inside a "box"(fixed area) with the following code as the new screenshot as shown below.

        val imageBitmap = imageResource(id = R.drawable.android)
        Image(
            modifier = Modifier
                .preferredSize(400.dp, 300.dp)
                .clip(RectangleShape)
                .zoomable(onZoomDelta = { scale.value *= it })
                .rawDragGestureFilter(
                    object : DragObserver {
                        override fun onDrag(dragDistance: Offset): Offset {
                            translate.value = translate.value.plus(dragDistance)
                            return super.onDrag(dragDistance)
                        }
                    })
                .graphicsLayer(
                    scaleX = scale.value,
                    scaleY = scale.value,
                    translationX = translate.value.x,
                    translationY = translate.value.y
                ),
            contentDescription = null,
            bitmap = imageBitmap
        )

enter image description here


Solution

  • Here is my solution... Might be helpful for someone...

    @Composable
    fun ZoomableImage() {
        val scale = remember { mutableStateOf(1f) }
        val rotationState = remember { mutableStateOf(1f) }
        Box(
            modifier = Modifier
                .clip(RectangleShape) // Clip the box content
                .fillMaxSize() // Give the size you want...
                .background(Color.Gray)
                .pointerInput(Unit) {
                    detectTransformGestures { centroid, pan, zoom, rotation ->
                        scale.value *= zoom
                        rotationState.value += rotation
                    }
                }
        ) {
            Image(
                modifier = Modifier
                    .align(Alignment.Center) // keep the image centralized into the Box
                    .graphicsLayer(
                        // adding some zoom limits (min 50%, max 200%)
                        scaleX = maxOf(.5f, minOf(3f, scale.value)),
                        scaleY = maxOf(.5f, minOf(3f, scale.value)),
                        rotationZ = rotationState.value
                    ),
                contentDescription = null,
                painter = painterResource(R.drawable.dog)
            )
        }
    }