如何在Jetpack Compose中实现图像的缩放和平移。

3
我有一个图像组合体,我希望用户能够放大图像的某一部分。例如,如果在图像的左下角捏住,那么就会放大该区域而不是图像中心。当缩放后,如果用一个手指,就可以在图像周围移动。
在我的当前代码中,我已经实现了捏合缩放的逻辑,但它默认是以图像中心为基准进行缩放,无论在哪里捏住图像。并且在缩放时没有对图像进行平移的逻辑。
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
                }
            }
        }
)

所以我想要实现两件事情:
  1. 能够缩放到实际被捏住的位置(而不是图像中心)
  2. 当放大时,能够在图像周围移动
我已经尝试了其他Stack Overflow答案的多个解决方案,但它们似乎都无效。
3个回答

3

有一个新发布的Compose库可以做到这一点,我个人没有尝试过,但它有很好的前景。

去看看 Telephoto

【旧回答】:

目前使用Compose无法实现该功能。

不过,我建议您使用AndroidView合成组件与 TouchImageView或类似组件进行互操作。


但它是否适用于Jetpack Compose? - Gourav Dadhich
你好@GouravDadhich,我已经更新了我的答案,添加了一个问题的组成实现。 - uragiristereo

0
可以通过以下方式实现允许平移的部分解决方案:
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()
)

(灵感来自ComposeZoomableImage


0
Roberto Leinardi的回答已经进行了一些小改动。 我在我的代码中设置了一个限制,以使图像不会超出容器。
@Composable
fun TouchImageView() {
    var zoom by remember { mutableStateOf(1f) }
    var offsetX by remember { mutableStateOf(0f) }
    var offsetY by remember { mutableStateOf(0f) }
    val minScale = 0.5f
    val maxScale = 2f

    Image(
        painter = painterResource(id = R.drawable.info_1),
        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) {
                            val maxOffsetX = 197.82568f \\chnange this to according to your image size
                            val maxOffsetY = 197.82568f
                            offsetX += pan.x * zoom
                            offsetY += pan.y * zoom
                            offsetX = offsetX.coerceIn(-maxOffsetX, maxOffsetX)
                            offsetY = offsetY.coerceIn(-maxOffsetY, maxOffsetY)
                        } else {
                            offsetX = 0f
                            offsetY = 0f
                        }
                    }
                )
            }
            .fillMaxSize()
    )
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接