Text 组件 API 与样式定制
Text 是 Jetpack Compose 中最基础的显示组件,负责在界面中输出字符串。它的样式定制能力覆盖字体、颜色、对齐、行数截断以及富文本标注。本章从参数体系、实现流程、调试手法到性能陷阱,完整覆盖 Text 的实用开发环节。
1. 核心参数体系
Text 组件最常用的参数分为三组:基础文本内容、排版样式、布局约束。以下表格列出关键参数及类型:
| 参数 | 类型 | 作用 |
|---|---|---|
| text | String / AnnotatedString | 要显示的文本或富文本 |
| modifier | Modifier | 尺寸、点击、装饰等外部布局修饰 |
| style | TextStyle | 定义字体族、大小、粗细、行高、字间距等 |
| color | Color | 文字颜色,可覆盖 style 中的颜色 |
| textAlign | TextAlign | 水平对齐方式:Start、End、Center、Justify |
| maxLines | Int | 最大行数,超出部分按 overflow 处理 |
| overflow | TextOverflow | 溢出时效果:Clip、Ellipsis、Visible |
| softWrap | Boolean | 是否允许自动换行(默认 true) |
所有样式参数都可以在 style 块中统一设置,也可以拆成独立参数覆盖。优先级:独立参数 > style 内对应字段。
2. 字体、颜色与对齐
字体通过 TextStyle 的 fontFamily 指定,可以设置系统字体或自定义字体族。颜色直接传 Color 对象,支持 Material 颜色体系或十六进制。
@Composable
fun StyledTextDemo() {
Text(
text = "Hello Compose",
style = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Medium,
fontSize = 18.sp,
color = Color(0xFF2C3E50),
textAlign = TextAlign.Center,
letterSpacing = 0.5.sp
),
modifier = Modifier.fillMaxWidth()
)
}
对齐不仅影响水平方向,也影响垂直行内基线。注意 TextAlign.Center 只对单行或多行整体水平居中有效;垂直居中需要配合 Modifier.wrapContentHeight(align = Alignment.CenterVertically) 实现。
3. maxLines 与 overflow
当文本过长时,使用 maxLines 限制行数,结合 overflow 决定溢出行为。有三种模式:
- Clip:直接裁剪超出的部分,无省略号。
- Ellipsis:在最后一行末尾显示省略号“…”(默认值)。
- Visible:溢出部分继续绘制,但可能超出父容器边界。
maxLines 和 Modifier.heightIn(max = ...) 时,可能因高度限制导致多余空白。优先用 maxLines 控制行数,行高由行距自动计算。
@Composable
fun TruncatedText() {
Text(
text = "这是一段非常长的文本,需要限制在三行以内并显示省略号。",
maxLines = 3,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.body1
)
}
4. AnnotatedString:富文本与交互
AnnotatedString 允许在同一个 Text 内对不同片段设置不同样式,甚至添加点击链接。常用构建方式是通过 buildAnnotatedString lambda。
append(string)—— 追加普通文本withStyle(style, content)—— 为一段文本应用 TextStylepushStringAnnotation(tag, value)—— 标记可交互区域pop()—— 结束当前标记
@Composable
fun AnnotatedTextDemo() {
val annotated = buildAnnotatedString {
withStyle(SpanStyle(color = Color.Red, fontWeight = FontWeight.Bold)) {
append("红色粗体")
}
append(" ")
withStyle(SpanStyle(fontStyle = FontStyle.Italic, fontSize = 20.sp)) {
append("斜体大字")
}
}
Text(text = annotated)
}
要实现字符串内部点击链接,需要配合 ClickableText 组件。示例如下:
@Composable
fun ClickableLinkText() {
val annotated = buildAnnotatedString {
pushStringAnnotation(tag = "url", annotation = "https://example.com")
withStyle(SpanStyle(color = Color.Blue, textDecoration = TextDecoration.Underline)) {
append("点击访问示例链接")
}
pop()
}
ClickableText(
text = annotated,
onClick = { offset ->
annotated.getStringAnnotations("url", offset, offset)
.firstOrNull()?.let { annotation ->
// 处理点击事件,例如打开浏览器
}
}
)
}
5. 调试与常见错误
在开发阶段,可以使用 Compose 的布局 inspector 查看 Text 的实际渲染区域。常见错误包括:
- 字体未生效: 确认
fontFamily引用的字体文件已放入res/font并在theme中正确配置。 - 颜色覆盖失效: 检查是否在
style中设置了颜色,同时又在组件参数里传了另一个color,后者优先级更高。 - maxLines 不生效: 确保没有使用
Modifier.height()固定高度,否则可能提前截断。 - AnnotatedString 文字不显示: 检查 buildAnnotatedString 中是否忘记
pop()或嵌套标记未闭合。
6. 性能与稳定性优化
Text 在编译期会测量字形,但高频重组时可能引发性能问题:
- 避免在 compose 中实时构建超长 AnnotatedString: 将富文本构建放到 remember 或 derivedStateOf 中,利用快照系统避免重复构建。
- 字体加载: 使用
FontFamily.Custom时,确保字体资源在首次渲染前已加载,否则出现延迟闪烁。考虑在 Application 初始化时预加载常用字体。 - overflow 与软换行: 大量文本且频繁 re-layout 时,可考虑将
softWrap = false并用水平滚动代替换行重绘,但需权衡可用性。
AnnotatedString 实例,避免 recomposition 阶段大量对象创建导致 GC 抖动。
7. 本章核心流程结构
下图概括了 Text 组件样式定制的完整流程及内部决策点:
左上角输入后,经过样式合并、对齐与截断判断,再根据内容类型选择普通绘制或富文本分段绘制,最终合成并提交到 Compose 内部缓存。