'How to implement zoom and pan on an Image in jetpack compose
I have an Image composable where I want the users to able to zoom into a part of the image. For example, if pinched on the bottom left of the image then zoom into that the bottom left area and not the center of the image. And when zoomed in then be able to pan around the image if a single finger.
In my current code, I have the pinch to zoom in & out logic but it defaults to the center of the image no matter where the image was pinched And there is no pan logic to the image when zoomed in.
Image(
painter = painterResource(id = R.drawable.sample_image),
contentDescription = "some description here",
modifier = Modifier
.graphicsLayer(
scaleX = scale.value,
scaleY = scale.value
)
.pointerInput(Unit) {
detectTransformGestures { _, _, zoom, _ ->
scale.value = when {
scale.value < 0.5f -> 0.5f
scale.value > 3f -> 3f
else -> scale.value * zoom
}
}
}
)
So I want to achieve two things:
- be able to zoom where it was actually pinched(not the center of the image)
- When Zoomed in, be able to pan around the image
I've tried implementing multiple solutions from other stack overflow answers but they don't seem to work.
Solution 1:[1]
There is currently not possible to do that with compose.
However i recommend you to interop with TouchImageView or similiar using AndroidView composable.
Solution 2:[2]
A partial solution that allows pan can be achieved like this:
var zoom by remember { mutableStateOf(1f) }
var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) }
val minScale = 0.5f
val maxScale = 3f
Image(
painter = painterResource(id = R.drawable.sample_image),
contentDescription = "some description here",
contentScale = ContentScale.Fit,
modifier = Modifier
.graphicsLayer(
scaleX = zoom,
scaleY = zoom,
translationX = offsetX,
translationY = offsetY,
)
.pointerInput(Unit) {
detectTransformGestures(
onGesture = { _, pan, gestureZoom, _ ->
zoom = (zoom * gestureZoom).coerceIn(minScale, maxScale)
if(zoom > 1) {
offsetX += pan.x * zoom
offsetY += pan.y * zoom
}else{
offsetX = 0f
offsetY = 0f
}
}
)
}
.fillMaxSize()
)
(inspired by ComposeZoomableImage)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | uragiristereo |
| Solution 2 |
