androidandroid-jetpack-compose

Compose Text wrapping to next line but width not reduced


I am working on Jetpack Compose UI in Android. I have a following Box which shows a Text.

@Preview
@Composable
fun MyText(modifier: Modifier = Modifier)
{
    Box(modifier = Modifier.heightIn(max = 94.dp).widthIn(max = 270.dp)
        .clip(shape = RoundedCornerShape(20.dp))
        .border(
             width = 1.dp,
             color = Color.Green,
             shape = RoundedCornerShape(20.dp)
        )
        .padding(horizontal = 20.dp, vertical = 8.dp)) {
        Text(
            text = "Learn how to use Compose effectively",
            overflow = TextOverflow.Ellipsis,
            maxLines = 3,
            fontSize = 15.sp,
            fontWeight = FontWeight.W400,
            color = Color.Red
        )
    }
}

It produces attached output. As you can see, "effectively" shifts to next line due to width constraints but it leaves much empty space after "Compose" in the first line. Is there a way to remove that extra left space so that overall width reduces?

enter image description here


Solution

  • You can try to use the onTextLayout callback to find out how long the longest line of the actual text is. Then, set the maximum width of the Text to the longest line length (rounded):

    @Preview
    @Composable
    fun MyText(modifier: Modifier = Modifier) {
    
        val localDensity = LocalDensity.current
        var textWidth by remember { mutableIntStateOf(Int.MAX_VALUE) }
    
        Box(
            modifier = Modifier
                .wrapContentWidth()
                .clip(shape = RoundedCornerShape(20.dp))
                .border(
                    width = 1.dp,
                    color = Color.Green,
                    shape = RoundedCornerShape(20.dp)
                )
                .padding(horizontal = 20.dp, vertical = 8.dp)
        ) {
    
            Text(
                modifier = Modifier
                    .requiredHeightIn(max = 94.dp)
                    .requiredWidthIn( max =
                        min(
                            localDensity.run { textWidth.toDp() },
                            230.dp
                        )
                    ),
                text = "Learn how to use Compose effectively",
                onTextLayout = { textLayoutResult ->
                    var longestLine = 0f
                    repeat(textLayoutResult.lineCount) { lineIndex ->
                        longestLine = max(longestLine, textLayoutResult.getLineRight(lineIndex))
                    }
                    textWidth = ceil(longestLine).toInt()
                },
                overflow = TextOverflow.Ellipsis,
                maxLines = 3,
                fontSize = 15.sp,
                fontWeight = FontWeight.W400,
                color = Color.Red
            )
        }
    }
    

    Note that I shifted all the Modifiers to the Text Composable and also adjusted the maximum width to not include the padding.

    Output:

    enter image description here