Jetpack compose: position elements inside a Box
Asked Answered
F

4

7

I have a Box in my app with a bunch of children:

Box(modifier = Modifier.fillMaxSize()) {
    Text("a")
    Text("b")
}

I want the text to appear aligned to the top at 20% distance from the start. How do I achieve that?

Foret answered 23/4, 2022 at 9:35 Comment(0)
F
2

Use the offset/absoluteOffset modifiers along with BoxWithConstraints.

Foret answered 25/4, 2022 at 9:10 Comment(2)
can you provide an exemple?Troxell
Please provide an example so that we can better understand your answer.Abort
R
14

To solve this you need two parts:

  1. There're two ways to layout Box content: contentAlignment will apply alignment for all children, and Modifier.align, which can be applied for a specific child.

  2. Usually you can use Modifier.padding in such cases, but not in case when you need relative size. The easiest way to take part of parent size is using Modifier.fillMax..., modifier, in this case Modifier.fillMaxWidth(0.2f) can be applied to a Spacer, placed in a Row with your element.

Box(modifier = Modifier.fillMaxSize()) {
    Row(
        Modifier
            .align(Alignment.TopStart)
    ) {
        Spacer(Modifier.fillMaxWidth(0.2f))
        Text("a")
    }
}
Rebeca answered 23/4, 2022 at 12:23 Comment(3)
The BoxWithConstraints did not work for me, this answer works for the first child in the Column or Row. However, for the other children, the fraction is applied to the size that is left to be filled, not the parent size, which is what I need.Inept
@PabloValdes I guess you can create a separate row for each item, and they're gonna be displayed on top of each otherRebeca
I tried that and it works great, thanks. I still have to get used to the compose way.Inept
G
4

follow thewolf's answer

I found this solution.

Let's check this code and the blue box below.

@Composable
fun BoxExample() {
    BoxWithConstraints {
        val boxWithConstraintsScope = this
        val yOffset = 0.2 * boxWithConstraintsScope.maxHeight.value

        Box(
            modifier = Modifier
                .fillMaxSize()
        ) {

            Box(
                modifier = Modifier
                    .height(300.dp)
                    .width(300.dp)
                    .background(Color.Red)

            )
            Box(
                modifier = Modifier
                    .height(200.dp)
                    .width(200.dp)
                    .background(Color.Green)
            )
            Box(
                modifier = Modifier
                    .offset(y =  yOffset.dp)
                    .height(100.dp)
                    .width(100.dp)
                    .background(Color.Blue)
            )
        }
    }
}

Look at Blue box

Genital answered 1/9, 2023 at 17:20 Comment(0)
F
2

Use the offset/absoluteOffset modifiers along with BoxWithConstraints.

Foret answered 25/4, 2022 at 9:10 Comment(2)
can you provide an exemple?Troxell
Please provide an example so that we can better understand your answer.Abort
O
0

Special Case: DropdownMenus

If you are working with DropdownMenus, the previous answers won't work with the resultant menus. DropDownMenus require something special as their menus don't honor the typical alignment instructions.

But I found that wrapContentSize(Alignment.some_alignment), an esoteric aspect of Modifier, seems to do the trick (although the documentation is beyond my comprehension).

This code will put both the icon and the menu itself at the top right of a Box that takes the whole screen width.

Box(
    modifier = modifier
        .fillMaxWidth()
        .wrapContentSize(Alignment.TopEnd)
) {
    MyDropdownIcon(...) { ... }
    DropdownMenu(...) { ... }
}

Hope this helps some people--took me hours to figure this out.

Offload answered 4/8, 2024 at 16:34 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.