Android parent (X,Y) 的可组合相对位置

Android Composable relative position to parent (X,Y)

我创建了一个 Canvas 可组合项,它允许我在 parent(Canvas)的边界内拖动和缩放 child 可组合项。

我需要知道 child 可组合项在被拖动或缩放时相对于其 parent(Canvas)在任何给定时间的位置。

GridCanvas(
    ratio = canvasRatio,
) { gridWidth, gridHeight ->

    var scale by remember { mutableStateOf(1f) }
    var offsetX by remember { mutableStateOf(0f) }
    var offsetY by remember { mutableStateOf(0f) }

    RenderedImage(
        modifier = Modifier
            .pointerInput(Unit) {
                detectTransformGestures { _, pan, zoom, _ ->
                    val futureScale = scale * zoom

                    if (futureScale in MIN_SCALE_FACTOR..MAX_SCALE_FACTOR) {
                        scale = futureScale
                    }

                    offsetX += pan.x
                    offsetY += pan.y
                }
            }
            .graphicsLayer {
                this.scaleX = scale
                this.scaleY = scale
                this.translationX = offsetX
                this.translationY = offsetY
            },
        imageUri = someUri,
    )
}

如何获取 child RenderedImage 相对于其 parent 的 XY 位置?

如果 needed.This 一个 returns 您在父级中的可组合位置,您也可以从 Modifier.onGloballyPosition{ it.positionInParent()} 获取它并在根和 window 中定位。

不同于View中的onTouchEventpointerInputChange事件从(0,0)开始,onTouchEvents使用window中View的全局位置。当您位于可组合偏移的顶角时,返回的是 (0,0)。

如果你想在你的 Composable 中获得触摸位置,你可以使用第一个参数 centroid,它 returns 指针中心 。如果你有一个向下的指针,它就是指针的触摸位置,当你有 2 个、3 个或更多指针时,它是相对于 Composble 开始向下的指针中心。如果您在父项中添加可组合项的初始位置,您也可以得到它。

假设您有一个如下所示的可组合项

Column(
    modifier = Modifier.fillMaxSize()
) {
    Box(modifier = Modifier.fillMaxWidth().height(100.dp).background(Color.Red))
    Column(modifier = Modifier.fillMaxWidth()) {
        Box(modifier = Modifier.fillMaxWidth().height(200.dp).background(Color.Yellow))
        MyComposable()
    }
}

还有你需要坐标的MyComposable

@Composable
private fun MyComposable() {


    var text by remember { mutableStateOf("") }
    Column(modifier = Modifier
        .fillMaxWidth()
        .height(300.dp)
        .border(2.dp, Color.Red)
        .onGloballyPositioned {
            val positionInParent: Offset = it.positionInParent()
            val positionInRoot: Offset = it.positionInRoot()
            val positionInWindow: Offset = it.positionInWindow()
            text =
                "positionInParent: $positionInParent\n" +
                        "positionInRoot: $positionInRoot\n" +
                        "positionInWindow: $positionInWindow"
        }
    ) {
        Text(text = text)
    }
}