Android Jetpack Compose中TextField组件的多样式文本编辑

5
我想在Android Jetpack Compose中使用按钮来更改TextField()组件中所选文本的文本样式(如字体大小、颜色、字重等)。
主要问题是,当我更改所选文本的文本样式时,TextField无法保存它,或者当我在TextField中添加/删除一个字母时,TextField会删除先前的文本样式。
换句话说,在重新组合过程发生时,TextField中的文本样式会消失。

enter image description here

我的代码是:
@Composable
fun Show() {

    val inputText = remember{ mutableStateOf(TextFieldValue("This is a annotated text text"))}
    Column(
        modifier = Modifier.fillMaxSize().padding(5.dp) ,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        //=================== TextField
        CustomTextField(textInput = inputText)
        //==================== Button
        Button(onClick = {
            inputText.value = changeSegmentColor(inputText.value)

        }) {
            Text(text = "Change the text style of selected text")
        }
        //======================
    }
}

@Composable
fun CustomTextField (
    textInput:MutableState<TextFieldValue>
) {
    TextField(
        value = textInput.value , onValueChange = {
            textInput.value = it
        },
        modifier = Modifier.fillMaxWidth().heightIn(min = 200.dp) ,
    )
}
private fun changeSegmentColor(textFVal: TextFieldValue):TextFieldValue{
    val txtAnnotatedBuilder = AnnotatedString.Builder()
    val realStartIndex = textFVal.getTextBeforeSelection(textFVal.text.length).length
    val endIndex = realStartIndex + textFVal.getSelectedText().length
    txtAnnotatedBuilder.append(textFVal.annotatedString)
    val myStyle = SpanStyle(
        color = Color.Red ,
        fontSize = 16.sp ,
        background = Color.Green
    )
    txtAnnotatedBuilder.addStyle(myStyle ,realStartIndex ,endIndex)
    return textFVal.copy(annotatedString = txtAnnotatedBuilder.toAnnotatedString())
}

你能成功构建一个显示格式化annotatedStrings的Text Composable吗?同时,请提供一个最小可复现示例。 - Richard Onslow Roper
1
这个回答解决了你的问题吗?如何在Jetpack Compose中更改TextField的高亮文本颜色? - nglauber
@MARSK,我能够在Text()组合中更改所选文本的样式(如fontSize,color等),但我不知道为什么TextField()组合无法保存样式。 TextField()组合是可编辑文本->在Xml中= EditText... - Amir
是的,我也遇到了这个错误。我会记录一个错误,除非你已经记录了? - Adam
我知道这并没有太大的帮助,但是这里已经有一个错误报告了。这个问题是由于EditingBuffer的toAnnotatedString()从纯文本版本创建一个新的AnnotatedString所导致的。它似乎缺少EditText具有的跨度支持(随着文本修改而增长、缩小、删除等)。 - Jorge Martín
显示剩余2条评论
1个回答

0
@Composable
fun MultiStyleText(text: String, vararg styleRanges: StyleRange) {
    val annotatedString = buildAnnotatedString {
        var currentPosition = 0

        styleRanges.forEach { range ->
            val style = SpanStyle(
                color = range.textColor,
                fontSize = range.textSizeSp.sp,
                fontWeight = range.fontWeight
            )
            withStyle(style) {
                append(text.substring(currentPosition, range.endIndex))
            }
            currentPosition = range.endIndex
        }

        // Append the remaining text with the default style
        withStyle(SpanStyle()) {
            append(text.substring(currentPosition))
        }
    }

    Text(text = annotatedString)
}




data class StyleRange(
    val startIndex: Int,
    val endIndex: Int,
    val textColor: Color,
    val textSizeSp: Float,
    val fontWeight: FontWeight
)

在上面的示例中,定义一个名为MultiStyleText的组合,它接受文本参数以及类型为StyleRange的可变数量的styleRanges。每个StyleRange指定要应用样式的文本范围的起始和结束索引,以及所需的文本颜色、文本大小和字体粗细。
在组合内部,迭代styleRanges并使用withStyle将相应的样式应用于指定的文本范围。使用append函数将每个样式范围内的相关子字符串附加text上。最后,使用默认样式附加剩余的文本。
要使用MultiStyleText组合,请提供所需的textstyleRanges
MultiStyleText(
    text = "This is a multi-style text example",
    StyleRange(0, 4, Color.Red, 18f, FontWeight.Bold),
    StyleRange(5, 7, Color.Blue, 14f, FontWeight.Normal),
    StyleRange(8, 13, Color.Green, 16f, FontWeight.Bold)
)

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接