androidandroid-jetpack-composeandroid-jetpack

Text Composable with custom suffix on overflow


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.


Solution

  • 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()
        )
    }