'Jetpack Compose: How do you position UI elements within their parent with exact (x,y) coordinates?

According to the documentation on custom layouts: "Each UI element has one parent and potentially many children. Each element is also located within its parent, specified as an (x, y) position, and a size, specified as a width and a height."

Let's say I have a Button inside of a Box. How can I specify the exact X and Y position for the Button inside that Box?



Solution 1:[1]

By default Box has TopStart alignment, which is the same as android coordinate space start point. To move from that point you can use offset modifier:

Box {
    Button(
        onClick = { /*TODO*/ },
        modifier = Modifier
            .offset(x = 100.dp, y = 100.dp)
    ) {

    }
}

Solution 2:[2]

For custom Layouts, the story is a bit different. You can read all about that in the Layouts Codelab - https://developer.android.com/codelabs/jetpack-compose-layouts#6

This tells how to design a column by hand.

Example, centering the element in the given constraints.

Layout(
        content = {
            Button(onClick = { /*TODO*/ }) {
                Text("Lorem Ipsum")
            }
        }
    ){measurables, constraints ->
        //Measuring the First (and only) item with the given constraints and storing the resulting placeable
        val placeable = measurables[0].measure(constraints)
        layout(constraints.maxWidth, constraints.maxHeight){ // Size of the Layout, can be anything you want, even a number
            placeable.place(constraints.maxWidth / 2, constraints.maxHeight / 2) // Placing at net half the distance
            //You can also specify the x, y above. That is what it is for.
        }
    }

And that's all

Solution 3:[3]

modifier = Modifier.layout { measurable, constraints ->
                        val placeable = measurable.measure(constraints)
                        layout(placeable.width, placeable.height) {
                           //  placeable.placeRelative(x.roundToPx(), y.roundToPx())
                            placeable.place(IntOffset(it.offset.x.roundToInt(), it.offset.y.roundToInt()))
                        }
                    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Pylyp Dukhov
Solution 2 marc_s
Solution 3 Abhijith mogaveera