Home > database >  Is it possible to build an evenly spaced and unconstrained grid in Compose?
Is it possible to build an evenly spaced and unconstrained grid in Compose?

Time:12-10

Is it possible to build a grid in compose, where the sizes of all elements are even, dictated by the largest content? I'd also like this grid to wrap the content and not be bound by any pre-set height.

So something like this. Let's assume the grid is full-width and we know there are only 2 columns.

 ____________ ____________
|      1.    |2. Medium   |
|Short stuff |length      |
|            |text        |
|____________|____________|
|3. This is  |            |
|a very long |4. hi!      |
|content here|            |
|____________|____________|

I've been trying to create something like this, but I don't think it's possible in Compose, without setting some sort of overall height of the grid?

You could have something like this:

@Composable
fun SampleGrid() {
    Row(modifier = Modifier.fillMaxWidth()) {
        Column(modifier = Modifier.weight(0.5f)) {
            Cell(modifier = Modifier.weight(0.5f))
            Cell(modifier = Modifier.weight(0.5f))
        }
        Column(modifier = Modifier.weight(0.5f)) {
            Cell(modifier = Modifier.weight(0.5f))
            Cell(modifier = Modifier.weight(0.5f))
        }
    }
}

So it's a nice 2x2, even grid, but the weigth will make the elements grow as high as it wants, until it's constrained by some other view around it or a container with a set height.

We can add on height(IntrinsicSize.Max) to the Column modifiers, so then it's kinda wrap content but what if the other column has a lot/less of content in it? The heights get out of sync

 ____________ ____________
|      1.    |2. hi!      |
|Short stuff |____________| 
|            |4. hi!      |
|____________|____________|
|3. This is  |
|a very long |
|content here|
|____________|

You can build a grid with a Column wrapper instead and multiple Rows, but you get the same issue.

I've found this is a problem even when using a custom Layout, and especially SubcomposeLayout. We can have one layout depend on another, but what if you calculate the height of one row, and it turns out the second row needs more space because it has more content? Then you'd have to re-measure the first one to make it larger, but it's not allowed to measure twice in Compose.

Is my understanding correct? Is a grid with evenly sized elements, which grows with its largest content (instead of being constrained by some height) impossible? Feels to me a bit like a chicken and egg kind of a problem...

CodePudding user response:

You can solve this with .height(IntrinsicSize.Min) applied to Row: it'll limit max height to the smallest Column height:

Row(
    modifier = Modifier
        .width(200.dp)
        .height(IntrinsicSize.Min)
) {
    Column(modifier = Modifier.weight(1f)) {
        Cell("Short stuff", modifier = Modifier.weight(1f))
        Cell(LoremIpsum(10).values.first(), modifier = Modifier.weight(1f))
    }
    Column(modifier = Modifier.weight(1f)) {
        Cell("Medium length text", modifier = Modifier.weight(1f))
        Cell("hi", modifier = Modifier.weight(1f))
    }
}

Result:

  • Related