11

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)

......

nayriz
  • 353
  • 1
  • 17
StuartDTO
  • 783
  • 7
  • 26
  • 72

5 Answers5

11

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

Skizo-ozᴉʞS ツ
  • 19,464
  • 18
  • 81
  • 148
11

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

dmastra
  • 439
  • 3
  • 9
7

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)) {}
}
daniyelp
  • 915
  • 1
  • 11
  • 26
  • Is it possible to don't make width and height hardcoded and do it "wrap_content"? – StuartDTO Jan 21 '22 at 13:12
  • @StuartDTO Why wouldn't it be possible? Omit the size modifiers. – daniyelp Jan 21 '22 at 13:43
  • So if I omit them they are wrap_content directly? I mean inside of my `Box` I have a `Row` with one Text and inside the other `Box` I have a `Row` with more than 1 `Text` so I want that Box (the below one the one with more `Text`) have the same width as the upper one, because the upper `Box` only contains one `Text` and it will be smaller – StuartDTO Jan 21 '22 at 13:50
  • @StuartDTO You'd need to somehow determine the width of the bigger Row. But if you omit the size modifier, the containers wrap around the content, yes. – daniyelp Jan 21 '22 at 14:39
  • I mean... with constraint layout this is easy to do, in theory Compose is way easier than XML maybe I can put an example in ConstraintLayout so you can help me better? – StuartDTO Jan 21 '22 at 20:28
  • @StuartDTO One way to solve it would be to calculate the size of the bigger Row and assign that to the smaller Row. I didn't do such thing yet. But if you say that you can do it easily with constraint layout, then do so. Jetpack Compose also has Constraint Layout. – daniyelp Jan 22 '22 at 13:29
  • Can you help me on this one @daniyelp https://stackoverflow.com/questions/71502444/compose-two-composables-overlaped-and-constraint-with-them – Skizo-ozᴉʞS ツ Mar 16 '22 at 19:51
2

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)
        )
    }
}
RaBaKa 78
  • 1,115
  • 7
  • 11
  • Is it possible to don't make width and height hardcoded and do it "wrap_content"? and btw contentAlignment is not reconized in Box. – StuartDTO Jan 21 '22 at 13:12
  • Please see the comment I've post on the other answer to understand it better – StuartDTO Jan 21 '22 at 13:52
  • I don't want to add a 200dp and height for the box I want to make it wrap content in terms of width... And the first Box be the same width as the one below even if the text is smaller. – StuartDTO Jan 21 '22 at 20:26
  • Can you help me on this one? https://stackoverflow.com/questions/71502444/compose-two-composables-overlaped-and-constraint-with-them – Skizo-ozᴉʞS ツ Mar 16 '22 at 19:51
0

I think you must use "matchParentSize" modifier that is avaliabele inside BoxScope, I mean inside Box composable, that modifer measure other children size except itself when it has join the composable at first time to apply the same size to itself.

you can see this modifier in documentation https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/BoxScope#(androidx.compose.ui.Modifier).matchParentSize()