I'm having a little trouble with <Intrinsics>. I w...
# compose
v
I'm having a little trouble with Intrinsics. I would like for the Text (yellow) to align with the bottom of only be as tall as the Image as indicated by the red dotted line. Can anyone spot if I am using
IntrinsicSize.Min
incorrectly or if I misunderstood?
Copy code
@Composable
fun SampleHeightSyncedRow() {
    Row(
        modifier = Modifier
            .height(IntrinsicSize.Min) // INTRINSIC SIZE SET HERE ON PARENT ROW
            .background(Color.Cyan),
        horizontalArrangement = Arrangement.spacedBy(10f)
    ) {
        Text(
            modifier = Modifier
                .weight(1f)
                .padding(start = 8.dp, top = 8.dp, bottom = 8.dp)
                .background(Color.Yellow),
            text = stringResource(id = R.string.sample_content)
        )
        Image(
            modifier = Modifier
                .weight(2f)
                .padding(end = 8.dp, top = 8.dp, bottom = 8.dp),
            painter = painterResource(id = R.drawable.apple_store),
            contentDescription = "Customers trying out new iPads at Apple Store."
        )
    }
}
k
Did you try
verticalAlignment=Alignment.Bottom
on your row?
Or do you want the text to only be as tall as the image?
v
The second one: I would like the text to only be as tall as the image. I also don't want to use Constraint Layout. Thanks!
k
Probably this is not something that a Row container will be able to give you.
At some point you bump into enough limitations of simpler containers that you need to go to more complex ones - because of the complexity of your requirements
v
I see. The Intrinsics Documentation states:
height(IntrinsicSize.Min)
 sizes its children being forced to be as tall as their minimum intrinsic height. As it's recursive, it'll query 
Row
 and its children 
minIntrinsicHeight
.
It also uses a Row with a few children. I'm wondering where I am going wrong.
k
Is your assumption that the min intrinsic height of your text is 0?
v
My expectation is that by adding the InstrinsicSize.Min modifier, the Row will recursively query the Text and Image Composable and set its height based on whatever child is the smallest. In this case, the Image.
So the Text would be clipped even though it has a large enough content String to expand if left unbounded.
f
it works the other way around. It measures the minimum height of the children and then picks the largest of those
👍 1
you can achieve what you want using a custom
Layout
you would measure the image based on your incoming constraints and aspect ratio and then set the layout height to the height of the image, then the text will clip as it's being constrained in height
v
@Francesc Thanks. Just to clarify your suggestion, do you mean to say I should use the Compose Constraint Layout API or a custom implementation of foundation's Layout.
f
no, a
Layout
composable and then you would measure and position the children yourself
👍 1
v
@Francesc Thanks for the help! I reviewed the docs for androidx.compose.ui Layout and the suggested androidx.compose.foundation BoxWithConstraints. These two seem like the right direction for this functionality. Added links here for anyone searching the Slack.
f
this should set you on the right path. This is specific to your text + image, but you could make it more generic
Copy code
@Composable
fun TextWithImage(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Layout(
        content = content,
        modifier = modifier,
    ) { measurables, constraints ->
        val text = measurables[0]
        val image = measurables[1]
        val imageConstraints = constraints.copy(
            minWidth = 0,
            minHeight = 0,
            maxWidth = (constraints.maxWidth * 2f / 3f).toInt(),
        )
        val imagePlaceable = image.measure(imageConstraints)
        val textWidth = constraints.maxWidth / 3f
        val textConstraints = Constraints.fixed(
            textWidth.toInt(),
            imagePlaceable.height
        )
        val textPlaceable = text.measure(textConstraints)
        layout(
            constraints.maxWidth,
            imagePlaceable.height
        ) { 
            textPlaceable.place(0, 0)
            imagePlaceable.place(textWidth.toInt(), 0)
        }
    }
}

@Preview
@Composable
fun TextWithImagePreview() {
    AppTheme {
        Surface(modifier = Modifier.width(320.dp)) {
            TextWithImage {
                Text(
                    modifier = Modifier.fillMaxWidth(),
                    text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus eleifend tempus laoreet. Fusce imperdiet dolor vitae mollis finibus. Sed faucibus, lorem ac vehicula molestie, diam mi euismod dui, eget commodo massa justo non enim. Cras eget iaculis ante. Cras et finibus lorem, sed varius turpis. Vestibulum in ante est. Integer sagittis, magna eu pretium sollicitudin, enim metus tristique dui, ac iaculis nulla nisl eu sem. Ut non turpis enim. Phasellus et nulla turpis. Pellentesque ligula lorem, lobortis vitae ultrices eget, consectetur a purus. Etiam pharetra orci sollicitudin nibh gravida consectetur."
                )
                Image(
                    modifier = Modifier.fillMaxWidth(),
                    painter = painterResource(id = R.drawable.sample), contentDescription = null
                )
            }
        }
    }
}
👏 3
🎉 2
v
@Francesc Awesome! That was more than expected. I attached the rendered preview for historical purposes and future reference for the rest of the Composers out there.
👍 2