kotlinandroid-jetpack-composeandroid-jetpackkotlin-multiplatformcompose-multiplatform

How, in Compose, set the size of an element to a specific children's size?


The setup

In Jetpack Compose, I have a Column (gray) with two elements, a long text (yellow) and a short text (cyan):

@Composable
@Preview
fun Foo() = Column(
    Modifier
        .background(Color.Gray)
        .fillMaxHeight()
) {
    // The long text
    Text(
        text = "Looooooooooooooooooong text",
        modifier = Modifier
            .background(Color.Yellow)
            .padding(20.dp)
    )
    // The short text
    Text(
        text = "Short text",
        modifier = Modifier
            .background(Color.Cyan)
            .padding(20.dp)
    )
}

The output looks like this:

first image

My problem

The short cyan text now has a lot of free space on the right. I want the cyan text to take that space and fill the whole width of the column, so that it has the same size as the long yellow text. So I tried adding .fillMaxWidth() to the short text like this:

@Composable
@Preview
fun Foo() = Column(
    Modifier
        .background(Color.Gray)
        .fillMaxHeight()
) {
    // The long text
    Text(
        text = "Looooooooooooooooooong text",
        modifier = Modifier
            .background(Color.Yellow)
            .padding(20.dp)
    )
    // The short text
    Text(
        text = "Short text",
        modifier = Modifier
            .background(Color.Cyan)
            .padding(20.dp)
            .fillMaxWidth() // <---------- NEW LINE ADDED HERE
    )
}

But it brought me this result:

second screenshot

As I did not limit the Column's width, the cyan text fills the maximal available width of the screen.

What I actually want

I want it to look like this:

third screenshot

(I created this picture by setting the column's width to a fixed length of 246 dp, however I don't want to set it manually because the column should be responsive to the yellow text's size)

So the cyan text should only fill the maximum available width of its parent, without increasing its parent's size.

So I either need a way to tell the cyan text not to stretch out like that, a modifier like .fillParentWidthButWithoutIncreasingIt(), or a way to tell the Column to always set its width to the width of the yellow text (however, for this I'd need a way to reference the yellow text or it's width).

Is one of these things possible? Or do I need a different approach?

Thank you and have a nice day


Solution

  • I recently had a similar issue myself and I solved it by using IntrinsicSize.Max
    In your case, set the width of the parent Column to IntrinsicSize.Max and then call .fillMaxWidth() on each Text composables.

    For more context, Compose’s intrinsic measurements are used to query the size children would take if laid out unconstrained, and then it uses that information to constrain the parent.

    Your final code should look like this:

    @Composable
    @Preview
    fun Foo() = Column(
        Modifier
            .background(Color.Gray)
            .fillMaxHeight()
            .width(IntrinsicSize.Max)
    ) {
        // The long text
        Text(
            text = "Looooooooooooooooooong text",
            modifier = Modifier
                .background(Color.Yellow)
                .padding(20.dp)
                .fillMaxWidth()
        )
        // The short text
        Text(
            text = "Short text",
            modifier = Modifier
                .background(Color.Cyan)
                .padding(20.dp)
                .fillMaxWidth()
        )
    }