如何在 Compose 中设置多行文本换行宽度?

net*_*men 9 android kotlin android-jetpack-compose

我想像这样画一个边框Text

Text("Box around text",
    modifier = Modifier
        .padding(top = 8.dp)
        .border(width = 2.dp, color = Color.Red)
        .background(Color.DarkGray))
Text("Box around text with a very very very very longlonglonglongword",
    modifier = Modifier
        .padding(top = 8.dp)
        .border(width = 2.dp, color = Color.Red)
        .background(Color.DarkGray)
)  
Run Code Online (Sandbox Code Playgroud)

但在多行文本的情况下,它看起来不太好。
右侧边框和文本之间有一个间隙。

文本周围的框

那么如何在多行文本周围绘制边框,使其适合文本宽度呢?

Phi*_*hov 11

它看起来像一个错误,我创建了这个问题

以下是您可以手动限制它的方法。

请注意,使用SubcomposeLayout可能会影响性能 - 或者,您可以通过将宽度存储在中来执行相同的技巧mutableStateOf- 这会提高性能,但也会使视图闪烁,因为在一帧内将渲染具有不受约束宽度的视图(或如果应用零 alpha,则具有相同大小的空白空间)。

@Composable
fun WrapTextContent(
    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,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    onTextLayout: (TextLayoutResult) -> Unit = {},
    style: TextStyle = LocalTextStyle.current,
) {
    SubcomposeLayout(modifier) { constraints ->
        val composable = @Composable { localOnTextLayout: (TextLayoutResult) -> Unit ->
            Text(
                text = text,
                color = color,
                fontSize = fontSize,
                fontStyle = fontStyle,
                fontWeight = fontWeight,
                fontFamily = fontFamily,
                letterSpacing = letterSpacing,
                textDecoration = textDecoration,
                textAlign = textAlign,
                lineHeight = lineHeight,
                overflow = overflow,
                softWrap = softWrap,
                maxLines = maxLines,
                onTextLayout = localOnTextLayout,
                style = style,
            )
        }
        var textWidthOpt: Int? = null
        subcompose("measureView") {
            composable { layoutResult ->
                textWidthOpt = (0 until layoutResult.lineCount)
                    .maxOf { line ->
                        ceil(layoutResult.getLineRight(line) - layoutResult.getLineLeft(line)).toInt()
                    }
            }
        }[0].measure(constraints)
        val textWidth = textWidthOpt!!
        val placeable = subcompose("content") {
            composable(onTextLayout)
        }[0].measure(constraints.copy(minWidth = textWidth, maxWidth = textWidth))

        layout(width = textWidth, height = placeable.height) {
            placeable.place(0, 0)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:


var textWidth by remember { mutableStateOf<Int?>(null) }
WrapTextContent(
    "Box around text with a very very very very longlonglonglongword",
    color = Color.White,
    modifier = Modifier
        .border(width = 2.dp, color = Color.Red)
        .background(Color.DarkGray)
)
Run Code Online (Sandbox Code Playgroud)

结果: