Jetpack Compose - TextOverflow.Ellipsis 在没有指定 maxLines 的情况下不起作用

Jetpack Compose - TextOverflow.Ellipsis doesn't work without specifying maxLines

我想在 Card 中显示一个 Text 并带有一些内部填充,有时文本不适合。我希望用省略号标记这个东西。但是没有 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
            )
        }
    }
}

maxLines = 2

使用 maxLines = 3 或根本不使用 maxLines

这是一个 known issue,导致 Ellipsis 忽略父大小限制。为它加星以引起更多关注并关注更新。

与此同时,您可以使用这个 hacky 解决方案:它会计算实际的行数并为 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)
        }
    }
}

用法:

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

结果: