1

I want to create a composable (shown in below image) where one box is larger and one smaller box is placed at bottom center of large box and bottom line of large box is passing through center of small box. How do I do that?

enter image description here

Annon
  • 633
  • 7
  • 26
  • Does this answer your question? [Overlap two Box jetpack compose](https://stackoverflow.com/questions/70799640/overlap-two-box-jetpack-compose) – Pratik Fagadiya Feb 28 '23 at 04:41

1 Answers1

2

You could use a custom layout:

@Composable
fun Boxes(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Layout(
        modifier = modifier,
        content = content,
    ) { measurables, constraints ->
        val largeBox = measurables[0]
        val smallBox = measurables[1]
        val looseConstraints = constraints.copy(
            minWidth = 0,
            minHeight = 0,
        )
        val largePlaceable = largeBox.measure(looseConstraints)
        val smallPlaceable = smallBox.measure(looseConstraints)
        layout(
            width = constraints.maxWidth,
            height = constraints.maxHeight
        ) {
            largePlaceable.placeRelative(0, 0)
            smallPlaceable.placeRelative(
                x = (constraints.maxWidth - smallPlaceable.width) / 2,
                y = largePlaceable.height - smallPlaceable.height / 2
            )
        }
    }
}

@Preview(widthDp = 420, heightDp = 720)
@Composable
fun BoxesPreview() {
    ComposePlaygroundTheme() {
        Surface(modifier = Modifier.fillMaxSize()) {
            Boxes(
                modifier = Modifier.fillMaxWidth()
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(128.dp)
                        .background(Color.Green)
                )
                Box(
                    modifier = Modifier
                        .width(128.dp)
                        .height(64.dp)
                        .background(Color.Red)
                )
            }
        }
    }
}

Sample

Edit: restricting the boxes height, use this

@Composable
fun Boxes(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Layout(
        modifier = modifier,
        content = content,
    ) { measurables, constraints ->
        val largeBox = measurables[0]
        val smallBox = measurables[1]
        val looseConstraints = constraints.copy(
            minWidth = 0,
            minHeight = 0,
        )
        val largePlaceable = largeBox.measure(looseConstraints)
        val smallPlaceable = smallBox.measure(looseConstraints)
        layout(
            width = constraints.maxWidth,
            height = largePlaceable.height + smallPlaceable.height / 2,
        ) {
            largePlaceable.placeRelative(
                x = 0,
                y = 0,
            )
            smallPlaceable.placeRelative(
                x = (constraints.maxWidth - smallPlaceable.width) / 2,
                y = largePlaceable.height - smallPlaceable.height / 2
            )
        }
    }
}

@Preview(widthDp = 420, heightDp = 720)
@Composable
fun BoxesPreview() {
    ComposePlaygroundTheme {
        Surface(modifier = Modifier.fillMaxSize()) {
            Column {
                Text(
                    text = "Before",
                    modifier = Modifier.padding(all = 16.dp)
                )
                Boxes(
                    modifier = Modifier.fillMaxWidth()
                ) {
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(128.dp)
                            .background(Color.Green)
                    )
                    Box(
                        modifier = Modifier
                            .width(128.dp)
                            .height(64.dp)
                            .background(Color.Red)
                    )
                }
                Text(
                    text = "After",
                    modifier = Modifier.padding(all = 16.dp)
                )
            }
        }
    }
}

In column

Francesc
  • 25,014
  • 10
  • 66
  • 84
  • I was able to use other composables by limiting `Boxes` height, but can't it work without providing height explicitly? – Annon May 18 '22 at 21:13
  • To resolve your issue change the layout to use the sum of the heights (large box height + half small box height), I'll update the response. – Francesc May 18 '22 at 22:40