【问题标题】:How to have Image zoom in Jetpack compose?如何在 Jetpack compose 中放大图像?
【发布时间】:2021-05-23 00:31:11
【问题描述】:

如果有人可以提供帮助,请在 jetpack 组合中像 Instagram 一样进行图像缩放

我想要这样的东西 https://drive.google.com/file/d/18a7SaPIoSObbvrmYxJ0GDhHXEETKpsEV/view?usp=drivesdk

【问题讨论】:

标签: android kotlin user-interface android-jetpack-compose


【解决方案1】:

1- 将刻度保存为状态

var scale by remember { mutableStateOf(1f) }

2- 设置图像的比例以使用此状态。我建议使用 graphicsLayer 设置比例以最小化无效内容,并添加您想要的任何其他转换,如下所示

Image(
        ...,
        modifier = Modifier
            .graphicsLayer(
                scaleX = scale,
                scaleY = scale
            )
    )

3- 使用Modifier.pointerInput 检测并应用缩放效果。使用 PointerInputScope,您可以检测选项卡和转换,即(缩放、旋转和平移)。例如,您可以添加以下内容来检测缩放手势并相应地修改比例。

modifier = Modifier
            .pointerInput(Unit) {
                detectTransformGestures { _, _, zoom, _ ->
                    scale = when {
                        scale < 0.5f -> 0.5f
                        scale > 3f -> 3f
                        else -> scale * zoom
                    }
                }
            }

detectTransformGestures 的其他参数是质心、平移和旋转。您不需要它们来进行缩放转换,但如果您尝试应用旋转和平移,您将需要它们。

如果您想使用平移手势应用缩放,您可以使用detectTapGestures。这是一个例子。

modifier = Modifier
            .pointerInput(Unit) {
                detectTapGestures(
                    onDoubleTap = {
                        scale = when {
                            scale > 2f -> 1f
                            else -> 3f
                        }
                    }
                )
            }

这是使用 CoilImage 的完整示例。任何其他图像的实现应该相同

@Composable fun SamplePreview(imageUrl: String) {
var scale by remember { mutableStateOf(1f) }
Box {
    CoilImage(
        data = imageUrl,
        contentDescription = null,
        contentScale = ContentScale.FillWidth,
        modifier = Modifier
            .align(Alignment.Center)
            .graphicsLayer(
                scaleX = scale,
                scaleY = scale
            )
            .pointerInput(Unit) {
                detectTransformGestures { _, _, zoom, _ ->
                    scale = when {
                        scale < 0.5f -> 0.5f
                        scale > 3f -> 3f
                        else -> scale * zoom
                    }
                }
            }
    ) {
        CircularProgressIndicator()
    }
}

【讨论】:

  • 在 lamdba 版本中使用 .graphicsLayer。它在不触发重组和重新布局的情况下更新可组合。比如:.graphicsLayer{ scaleX = scale; scaleY = scale}
  • @GabrieleMariotti 您提出的更改听起来不错,但不幸的是它不起作用。如果您有可用的代码,我很乐意尝试 :-) 谢谢!
  • 感谢工作代码 Mostafa。一个小的改进:您可以将其替换为:scale = (scale * zoom).coerceIn(0.5f, 3f),而不是使用when,它的工作原理完全相同
【解决方案2】:

你有进步吗?我可以缩放图像,但是当用户终止手势时,我无法将图像恢复到原始大小。 要缩放图像,我所做的是: 创建了比例和状态变量。 if(scale &lt; 1) 是为了不让用户最小化图片。

var scale by remember { mutableStateOf(1f) }
val state = rememberTransformableState { zoomChange, _, _ ->
                scale *= zoomChange
                if(scale < 1){
                    scale = 1F
                }
        }

在图片中,我使用了graphicsLayer和transformable。

.graphicsLayer{
                    scaleX = scale;
                    scaleY = scale
                }
.transformable(state = state)

我试图捕捉用户的 MotionEvent,但没有找到观察到捏合手势的 MotionEvent。 另外,在.pointerInput 中我不能同时使用detectTapGestures 和detectTransformGestures,因为指针只考虑一个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 1970-01-01
    • 1970-01-01
    • 2022-08-17
    • 2019-11-08
    • 2023-01-21
    相关资源
    最近更新 更多