How to compose a new UI element from two Widgets?

Viewed 696

Image I have a normal Button in Android and a Star icon. I would like to compose them into a new Button icon, where the star is in one of the upper corners like here:

enter image description here

When I use Row both are seperated. As you can see, the star shall overlap the Button in one of its corner. How can I do that?

EDIT: Thanks to Gabriele Mariotti I used

Box {

    Button(
        id = "btnButton",
        modifier = Modifier
            .padding(end = 48)
        onClick = {
            //..
        }
    )

    IconWithStar(
        modifier = Modifier
            .scale(0.65f)
    )
}

Star icon is bound to upper left corner, how would I modify that?

1 Answers

You can wrap the composables with a Box and use the align/offset modifier to adjust the positions of them.

Box(Modifier.padding(top=40.dp)){
    Button(
        onClick = {}) 
    {
        Text("Hello World")
    }
    Icon(
        Icons.Filled.Star, "",
        modifier =Modifier
            .align(TopEnd)
            .offset(12.dp,-12.dp),
        tint = Yellow600
    )
}

enter image description here

To have more control you can build a custom Layout.
Something like:

Layout( content = {

        Button(
            modifier = Modifier.layoutId("button"),
            onClick = { /* ... */ })
        {
            Text("Hello World")
        }
        Icon(Icons.Filled.Star, "",
            Modifier.layoutId("icon"),
            tint = Yellow600)
}){ measurables, incomingConstraints ->

    val constraints = incomingConstraints.copy(minWidth = 0, minHeight = 0)
    val buttonPlaceable =
        measurables.find { it.layoutId == "button" }?.measure(constraints)
    val iconPlaceable =
        measurables.find { it.layoutId == "icon" }?.measure(constraints)

    //align the icon on the top/end edge
    layout(width = widthOrZero(buttonPlaceable) + widthOrZero(iconPlaceable)/2,
        height = heightOrZero(buttonPlaceable)+ heightOrZero(iconPlaceable)/2){

        buttonPlaceable?.placeRelative(0, heightOrZero(iconPlaceable)/2)
        iconPlaceable?.placeRelative(widthOrZero(buttonPlaceable)- widthOrZero(iconPlaceable)/2,
           0)

    }
}


internal fun widthOrZero(placeable: Placeable?) = placeable?.width ?: 0
internal fun heightOrZero(placeable: Placeable?) = placeable?.height ?: 0

enter image description here

Related