Android Composable 相对于父布局的位置 (X,Y)

5
我创建了一个Canvas组合,可以让我在父组合(Canvas)的范围内拖动和缩放子组合。
当子组合被拖动或缩放时,我需要知道它相对于其父组合(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,
    )
}


如何获取子级RenderedImage相对于其父级的XY位置?
1个回答

3

您可以从 Modifier.onGloballyPosition{ it.positionInParent()} 获取它,并且如果需要,也可以在根和窗口中获取位置。此方法返回您的组合位置相对于父级的位置。

与View中的onTouchEvent不同,pointerInputChange事件从(0,0)开始,而onTouchEvents使用视图在窗口中的全局位置。当您位于Composable Offset的左上角时,返回的偏移量为(0,0)。

如果您想获取组合内部的触摸位置,则可以使用第一个参数centroid,它返回指针中心的位置。如果您有一个指针按下,它就是指针的触摸位置,当您有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)
    }
}

我的意图是在子组件被拖动或缩放时知道其位置。onGloballyPositioned 只会被调用一次。不过,我已经更新了我的问题以使其更加清晰! :) - TareK Khoury
@TareKKhoury onGloballyPositioned会在您的组合件进入组合时被多次调用,但我明白了您的意思,并更新了我的答案。如果您想要触摸位置,可以使用onGesture: (centroid: Offset, pan: Offset, zoom: Float, rotation: Float) -> Unit的第一个参数。如果您只有单个指针按下,则此函数返回该指针的位置;当您有多个指针时,它将返回触摸中心。但是,组合件中的触摸系统从0开始,这就是为什么我问您是否需要父级位置的原因。在左上角,使用一个指针,您将得到0,0作为偏移量。 - Thracian
如果质心不足够,您总是需要第一个指针的触摸位置,您可以添加另一个 pointerInput(Unit) 并从中获取触摸位置,同时使用 detectTransformgestures 进行缩放、旋转或平移。您可以拥有多个 Modifier.pointerInput(Unit),每个都具有不同的角色,并且一个没有不会影响其他,这取决于您如何消耗 pointerInputChange - Thracian

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