一、核心含义与作用
buildAnnotatedString 是 Jetpack Compose 中专门用于构建带样式 / 标记的富文本字符串的核心函数,你可以把它理解为「Compose 版的 SpannableString(Android 传统富文本)」,但用法更简洁、更符合 Compose 的声明式风格。
- 字面意思 :
build(构建) +Annotated(带注解 / 标记的) +String(字符串),即「构建一个带标记 / 样式的字符串」。 - 核心价值 :突破普通
String只能单一样式的限制,让一段文本中不同部分拥有不同样式 (如部分文字变色、加粗、下标),或给部分文本添加自定义标记(如可点击的文本区域、跳转链接)。 - 使用场景:富文本显示、可点击的文本片段(如隐私政策)、带特殊格式的文本(如数学公式、金额)。
二、基础用法:核心语法
buildAnnotatedString 是一个构建器函数,内部通过链式调用的方式拼接文本和样式,核心语法如下:
kotlin
@Composable
fun BuildAnnotatedStringBasic() {
// 1. 构建带注解的字符串
val annotatedText = buildAnnotatedString {
// ① 追加普通文本
append("普通文本")
// ② 追加带样式的文本(withStyle + SpanStyle)
withStyle(
style = SpanStyle( // 文本样式:颜色、字号、粗细等
color = Color.Red,
fontWeight = FontWeight.Bold,
fontSize = 18.sp
)
) {
append("带样式的文本") // 这个范围内的文本会应用上述样式
}
// ③ 继续追加普通文本(样式回到默认)
append("普通文本")
}
// 2. 用 Text 组件显示
Text(text = annotatedText, modifier = Modifier.padding(16.dp))
}
三、关键 API 详解
buildAnnotatedString 内部支持的核心方法,按用途分为两类:
1. 样式相关(修改文本外观)
| 方法 | 作用 |
|---|---|
append(text: String) |
追加普通文本(无样式) |
withStyle(style: SpanStyle) |
给代码块内的文本应用样式(SpanStyle 是文本样式的封装) |
SpanStyle |
文本样式类,支持 color、fontSize、fontWeight、baselineShift(下标 / 上标)、textDecoration(下划线 / 删除线)等 |
2. 标记相关(给文本加自定义注解,用于交互)
| 方法 | 作用 |
|---|---|
pushStringAnnotation(tag: String, annotation: String) |
给后续文本添加「字符串标记」(key-value 形式),用于识别可点击区域 |
pop() |
结束当前标记 / 样式的作用范围(必须和 push/pushStyle 成对出现) |
四、典型示例:带点击标记的富文本
这是 buildAnnotatedString 最常用的场景(如隐私政策、用户协议),结合 ClickableText 实现部分文本点击:
ini
@Composable
fun AnnotatedStringWithClick() {
// 1. 构建带点击标记的 AnnotatedString
val policyText = buildAnnotatedString {
append("注册即同意")
// ① 给「隐私政策」添加标记
pushStringAnnotation(
tag = "PRIVACY", // 标记标签(自定义,用于识别)
annotation = "隐私政策链接" // 标记内容(可传链接、ID 等)
)
// ② 给标记文本加样式(蓝色、下划线)
withStyle(
style = SpanStyle(
color = Color.Blue,
textDecoration = TextDecoration.Underline
)
) {
append("隐私政策")
}
pop() // ③ 结束标记和样式(必须调用,否则后续文本都会带标记)
append("和")
// 同理,给「用户协议」加标记
pushStringAnnotation(tag = "USER", annotation = "用户协议链接")
withStyle(
style = SpanStyle(color = Color.Blue, textDecoration = TextDecoration.Underline)
) {
append("用户协议")
}
pop()
}
// 2. 用 ClickableText 显示(支持点击事件)
ClickableText(
text = policyText,
onClick = { offset ->
// 根据点击位置,获取对应的标记
policyText.getStringAnnotations(
tag = "PRIVACY",
start = offset,
end = offset
).firstOrNull()?.let {
// 点击了「隐私政策」
println("点击了:隐私政策")
}
policyText.getStringAnnotations(
tag = "USER",
start = offset,
end = offset
).firstOrNull()?.let {
// 点击了「用户协议」
println("点击了:用户协议")
}
},
modifier = Modifier.padding(16.dp)
)
}
五、关键注意事项
-
成对调用 push/pop :使用
pushStringAnnotation或pushStyle后,必须调用pop()结束作用范围,否则后续所有文本都会继承该标记 / 样式。 -
仅支持 Text/ClickableText :
AnnotatedString只能传给Text或ClickableText的text参数,不能直接作为普通字符串使用。 -
样式优先级 :
withStyle内部的样式会覆盖外部的默认样式,且内层样式会覆盖外层样式。 -
性能优化 :如果
AnnotatedString内容固定,用remember缓存,避免每次重组重新构建:
ini
val cachedText = remember {
buildAnnotatedString { /* 构建逻辑 */ }
}