5

Is there any option to change default ellipsis suffix (TextOverflow.Ellipsis) with a custom one in multiline text using Jetpack Compose?

"Long-long-long text to be ellipsized" -> "Long-long-long text to be... etc.".

Solutions using Row, alignment and two Text composables were not suitable for multiline Text. I want the suffix to be placed exactly in the end of first Text, if overflow occurs. But may be I missed something here. Anyway I will be glad for any help.

1
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. Commented Jul 30, 2024 at 0:51

1 Answer 1

4

Simply you can write a function using a Box container within BasixText and setting the width of your box container to set the text with your desired concatenation string.

val longText = "This is a very long text that should be truncated with a custom ellipsis if it exceeds the maximum number of lines set for this text component."
val customEllipsis = " .....[more]"
val textStyle = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Normal, color = Color.Black)

val textMeasurer = rememberTextMeasurer()
val constraints = Constraints(maxWidth = Int.MAX_VALUE)

val fullTextLayoutResult = textMeasurer.measure(
    text = AnnotatedString(longText),
    style = textStyle,
    constraints = constraints
)

val ellipsisLayoutResult = textMeasurer.measure(
    text = AnnotatedString(customEllipsis),
    style = textStyle,
    constraints = constraints
)

val maxWidth = 340.dp.dpToPx() // You can set the max width with your desired Width in dps
val textWithCustomEllipsis = if (fullTextLayoutResult.size.width > maxWidth) {
    var endIndex = longText.length
    var currentWidth = fullTextLayoutResult.size.width

    while (currentWidth + ellipsisLayoutResult.size.width > maxWidth && endIndex > 0) {
        endIndex--
        val truncatedText = longText.substring(0, endIndex)
        currentWidth = textMeasurer.measure(
            text = AnnotatedString(truncatedText),
            style = textStyle,
            constraints = constraints
        ).size.width
    }

    longText.substring(0, endIndex) + customEllipsis
} else {
    longText
}

Box(modifier = Modifier.padding(16.dp)) {
    BasicText(
        text = textWithCustomEllipsis,
        style = textStyle,
        modifier = Modifier.fillMaxWidth()
    )
}
Sign up to request clarification or add additional context in comments.

3 Comments

This is exactly how i would have done it, upvoted. TextMeasurer is way to go to but default Constraints already have maxWidth and maxHeight as Constraints.Infinity or Int.MAX_VALUE, i don't think it's needed when you need infinite Constraints but the constraints what you should be passing might be the screen width or Composable width such as 1080 or 1240. Otherwise it doesn't calculate texts as multiline as i recall
As the constraint is set to the text and the text is within the box, the text becomes multi-lines with the check of a given size which is set as the name of maxWidth variable
I have implemented the same solution and the width that I have passed defines the constraints or the screen width in dps

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.