Overlap two Box jetpack compose

Viewed 5023

I'm trying to overlap two Box or perhaps is better to use Row on this case.

My design is one Row overlapped with another one, and I've wrapped it on a Column, is that correct?

This is the design, what I'd like to have is the rectangle of the top be the same size of the one below and then move it some pixels as you can see in the image, but they should have the same width but not the same height.

enter image description here

Is it okay if the hierarchy is :

Column 
  Box (the one of the top)
    Row
  Box (the one of the bottom)
    Row (inside there is text and it's all the same align)
5 Answers

I've faced with this some days ago and I solved it using ConstraintLayout.

What I had to do is :

  1. Add implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02" to build.gradle
  2. Wrap every Box in a ConstraintLayout { .. }
  3. Inside each Box add a Modifier.constrainAs to align the Top Bottom Start End as you want.
  4. If you want the first box be the same width as the second one without hardcoding the dps you should use width = Dimension.fillToConstraints

fillToConstraints - the layout will expand to fill the space defined by its constraints in that dimension.

Basic example without hard-coding :

ConstraintLayout() {
            val (title, description) = createRefs()
            Box(
                modifier = Modifier
                    .padding(start = 28.dp)
                    .background(color = Red)
                    .padding(
                        horizontal = 16.dp,
                    )
                    .constrainAs(title) {
                        top.linkTo(parent.top)
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                        width = Dimension.fillToConstraints
                    }
            ) {
                Text(text = "Hello World")
            }

            Box(
                modifier = Modifier
                    .padding(end = 4.dp)
                    .background(Color.Magenta)
                    .padding(bottom = 5.dp, start = 8.dp, end = 16.dp, top = 4.dp)
                    .constrainAs(description) {
                        top.linkTo(title.top, margin = 16.dp)
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                        bottom.linkTo(parent.bottom)
                    }
            ) {
                Text(text = "Skizo-ozᴉʞS rules")
            }
        }

Now you have to play with the padding according to your UI and adapt it, result is something like this :

enter image description here

This is way using BoxWithConstraints and not using fixed width and height:

BoxWithConstraints(
    Modifier
        .background(color = Color.Blue)
        .padding(20.dp)) {

    val boxWidth = this.maxWidth
    Box(
        modifier = Modifier
            .width(boxWidth - 10.dp)
            .background(Color.Red)
    ) {
        Text(text = "Hello Android")
    }
    Column() {
        Spacer(modifier = Modifier
            .height(10.dp)
            .width(10.dp))
        Row( ) {
            Spacer(modifier = Modifier.width(10.dp))
            Box(
                modifier = Modifier
                    .width(boxWidth)
                    .zIndex(2f)
                    .background(Color.Yellow)
            ) {
                Text("aa", modifier = Modifier.background(color = Color.Green))
            }
        }
    }
}

two boxes same width

In order for the Composables to overlap, you should put them in the same Box. Try this out:

Box(modifier = Modifier.size(width = 300.dp, height = 100.dp)) {
    Row(modifier = Modifier
        .size(width = 200.dp, height = 50.dp)
        .background(color = Color.Blue)
        .align(Alignment.TopEnd)) {}
    Row(modifier = Modifier
        .size(width = 200.dp, height = 70.dp)
        .background(color = Color.Red)
        .align(Alignment.BottomStart)) {}
}

You can achieve this in many ways,

@Composable
fun BoxOverBox() {
    Box(
        modifier = Modifier.fillMaxSize()
            .background(Color.White),
        contentAlignment = Alignment.Center
    ) {
        Box(
            modifier = Modifier
                .width(200.dp)
                .height(50.dp)
                .background(Color.Red)
        )
        Box(
            modifier = Modifier
                .width(200.dp)
                .height(50.dp)
                .zIndex(2f)
                .graphicsLayer {
                    translationX = -50f
                    translationY = 50f
                }
                .background(Color.Blue)
        )
    }
}
Related