androidandroid-jetpack-compose

How to control text wrapping behaviour of two multiline text inside a Row in Jetpack compose?


How to achieve this behaviour in Jetpack compose using Row with two Text composables?

enter image description here

I have tried using Modifier.weight(1f) as below, but that only works assuming both text are longer than half the width of the Row and span multiple lines. Even though one of the text is a short one, they will always take 50% of the Row width, which is not what is desired.

Row(
    modifier = Modifier.width(width = 200.dp)
) {
    Text(
        text = "First text is aaa veeery very very long text",
        color = Color.Blue,
        modifier = Modifier.weight(1f)
    )
    Spacer(modifier = Modifier.width(4.dp))
    Text(
        text = "Second text is a very long text",
        modifier = Modifier.weight(1f)
    )
}

enter image description here


Solution

  • Got it to work by utilising TextMeasurer to pre calculate both the text widths, then only apply Modifier.weight(1f, false) when they exceed half of the parent width.

    val textMeasurer = rememberTextMeasurer()
    val firstText = "First text"
    val secondText = "Second text is a very long text"
    val density = LocalDensity.current
    val firstTextWidth = with(density) { textMeasurer.measure(text = firstText).size.width.toDp() }
    val secondTextWidth = with(density) { textMeasurer.measure(text = secondText).size.width.toDp() }
    
    BoxWithConstraints {
        val maxWidth = maxWidth
        Row(
            modifier = Modifier.width(width = 200.dp)
        ) {
            Text(
                text = firstText,
                color = Color.Blue,
                modifier = if (firstTextWidth > maxWidth / 2) {
                    Modifier.weight(1f, false)
                } else {
                    Modifier
                }
            )
            Spacer(modifier = Modifier.width(4.dp))
            Text(
                text = secondText,
                modifier = if (secondTextWidth > maxWidth / 2) {
                    Modifier.weight(1f, false)
                } else {
                    Modifier
                }
            )
        }
    }
    

    Seems to work but do wonder if there's a simpler way.