Android Composable relative position to parent (X,Y)

Viewed 358

I have a Canvas composable I created that allows me to drag and scale a child composable within the boundaries of the parent (the Canvas).

I need to know what is the position of the child composable relative to its parent (the Canvas) at any given time while being dragged or scaled.

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,
    )
}

How to get the X and Y position of the child RenderedImage relative to its parent?

1 Answers

You can get it from Modifier.onGloballyPosition{ it.positionInParent()} and position in root and in window too if needed.This one returns your Composable position in parent.

Unlike onTouchEvent in View, pointerInputChange events start from (0,0), onTouchEvents use global position of View in window. When you are at top corner of your Composable Offset that is returned is (0,0).

If you want to get touch position inside your Composable you can use first param which is centroid, it returns the center of pointers. if you have one pointer down, it's pointer's touch position, when you have 2, 3, or more it's center of pointers that are down relative to start of your Composble. If you add the initial position of your Composable in parent you can get that either.

Let's say you have a composable like the one below

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()
    }
}

And MyComposable which you need coordinates

@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)
    }
}
Related