Home > Back-end >  Jetpack Compose - TextOverflow.Ellipsis doesn't work without specifying maxLines
Jetpack Compose - TextOverflow.Ellipsis doesn't work without specifying maxLines

Time:11-12

I want to display a Text inside a Card with some inner padding and sometimes the text will not fit in. I want this thing to be marked with an ellipsis. But I can't make it work without maxLines.

@Composable
fun CardWithText() {
    Card(
        modifier = Modifier
            .height(60.dp)
            .width(100.dp)
            .border(1.dp, Color.Black, RoundedCornerShape(0))
    ) {
        Card(
            modifier = Modifier
                .padding(8.dp)
                .fillMaxSize()
                .border(1.dp, Color.Black, RoundedCornerShape(0))
        ) {
            Text(
                text = "One two three four five six seven eight nine ten eleven twelve",
                maxLines = 2,
                overflow = TextOverflow.Ellipsis,
                color = Color.Black
            )
        }
    }
}

With maxLines = 2

enter image description here

With maxLines = 3 or not using maxLines at all

enter image description here

CodePudding user response:

This is a known issue, causing Ellipsis to ignore parent size constraints. Star it to bring more attention and follow the updates.

Meanwhile you can use this hacky solution: it'll calculate the real number of lines and pass the correct value for maxLines:

@Composable
fun TextEllipsisFixed(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    onTextLayout: (TextLayoutResult) -> Unit,
    style: TextStyle = LocalTextStyle.current,
) {
    SubcomposeLayout(modifier = modifier) { constraints ->
        var slotId = 0
        fun placeText(
            text: String,
            onTextLayout: (TextLayoutResult) -> Unit,
            constraints: Constraints,
            maxLines: Int,
        ) = subcompose(slotId  ) {
            Text(
                text = text,
                color = color,
                fontSize = fontSize,
                fontStyle = fontStyle,
                fontWeight = fontWeight,
                fontFamily = fontFamily,
                letterSpacing = letterSpacing,
                textDecoration = textDecoration,
                textAlign = textAlign,
                lineHeight = lineHeight,
                softWrap = softWrap,
                onTextLayout = onTextLayout,
                style = style,
                overflow = TextOverflow.Ellipsis,
                maxLines = maxLines,
            )
        }[0].measure(constraints)
        var textLayoutResult: TextLayoutResult? = null
        val initialPlaceable = placeText(
            text = text,
            constraints = constraints,
            onTextLayout = {
                textLayoutResult = it
            },
            maxLines = maxLines,
        )
        val finalPlaceable = textLayoutResult?.let { layoutResult ->
            if (!layoutResult.didOverflowHeight) return@let initialPlaceable
            val lastVisibleLine = (0 until layoutResult.lineCount)
                .last {
                    layoutResult.getLineBottom(it) <= layoutResult.size.height
            }
            placeText(
                text = text,
                constraints = constraints,
                onTextLayout = onTextLayout,
                maxLines = lastVisibleLine   1,
            )
        } ?: initialPlaceable

        layout(
            width = finalPlaceable.width,
            height = finalPlaceable.height
        ) {
            finalPlaceable.place(0, 0)
        }
    }
}

Usage:

Card(
    modifier = Modifier
        .height(60.dp)
        .width(100.dp)
        .border(1.dp, Color.Black, RoundedCornerShape(0))
) {
    Card(
        modifier = Modifier
            .padding(8.dp)
            .fillMaxSize()
            .border(1.dp, Color.Black, RoundedCornerShape(0))
    ) {
        TextEllipsisFixed(
            text = "One two three four five six seven eight nine ten eleven twelve",
            color = Color.Black
        )
    }
}

Result:

  • Related