5、文本组件:Text 与 TextField 的使用、字体样式、颜色、对齐方式

文本,是任何UI界面最基础的构成元素。不管是显示一段静态文字,还是让用户输入内容,Compose 都提供了非常简洁的 API。今天我们就来聊聊 Text 和 TextField 这两个组件,以及如何控制它们的样式、颜色和对齐方式。

说实话,我刚从传统 View 体系转到 Compose 时,最不习惯的就是文本样式的写法。以前在 XML 里写一堆属性,现在全变成了 Kotlin 代码。但用习惯了你会发现,这种方式其实更灵活,也更符合声明式 UI 的思维。

5.1 Text:显示静态文本

Text 组件,说白了就是用来展示文字的。最简单的用法,一行代码搞定:

@Composable
fun SimpleText() {
    Text("Hello, Compose!")
}

但实际项目中,我们很少只用默认样式。你需要控制字体大小、颜色、粗细、行高等等。这些都可以通过 style 参数来设置。

5.1.1 字体样式与颜色

我个人习惯把常用的文本样式封装成常量,方便复用。比如这样:

val titleStyle = TextStyle(
    fontSize = 24.sp,
    fontWeight = FontWeight.Bold,
    color = Color(0xFF1A1A2E),
    letterSpacing = 0.5.sp
)

@Composable
fun TitleText(text: String) {
    Text(
        text = text,
        style = titleStyle
    )
}

颜色这块,Compose 提供了 Color 类,你可以直接用预定义的颜色,比如 Color.RedColor.Blue,也可以用 ARGB 或十六进制值。我在项目中遇到过一个问题:用 Color(0xFF000000) 表示黑色,但注意前面两位是透明度,FF 表示完全不透明。如果你写成 0x000000,那就变成全透明了——文字直接消失,排查了半天才发现。

注意:Color 的构造函数接收的是 Long 类型,但十六进制字面量默认是 Int。如果你写 Color(0xFF1A1A2E),编译器会报类型不匹配。正确的写法是 Color(0xFF1A1A2E.toInt()),或者直接用 Color(0xFF1A1A2E) 并确保 Kotlin 版本支持。嗯,这里要注意。

5.1.2 对齐方式

文本对齐,通过 textAlign 参数控制。它接受 TextAlign 枚举值:

Text(
    text = "这是一段居中对齐的文字",
    textAlign = TextAlign.Center,
    modifier = Modifier.fillMaxWidth()
)

你可能会问:为什么还要加 Modifier.fillMaxWidth()?因为 Text 默认宽度是包裹内容的,如果不占满父容器,居中对齐的效果就看不出来。我刚开始学 Compose 时就踩过这个坑,文字明明设置了居中,但看起来还是左对齐——其实就是宽度没撑开。

对齐方式 说明
TextAlign.Start 起始对齐(LTR 为左,RTL 为右)
TextAlign.End 末尾对齐
TextAlign.Center 居中对齐
TextAlign.Justify 两端对齐(多行文本有效)

5.2 TextField:用户输入文本

TextField 是 Compose 中用于接收用户输入的组件。它分为两种:TextField(Material Design 2 风格)和 OutlinedTextField(带外边框)。我个人更推荐用 OutlinedTextField,视觉上更清晰。

5.2.1 基本用法

TextField 是一个受控组件,你需要维护一个状态变量:

@Composable
fun InputField() {
    var text by remember { mutableStateOf("") }

    OutlinedTextField(
        value = text,
        onValueChange = { newText -> text = newText },
        label = { Text("请输入内容") },
        modifier = Modifier.fillMaxWidth()
    )
}

这里用到了 remembermutableStateOf,确保输入框的值在重组时不会丢失。嗯,这是 Compose 状态管理的核心,后面我们会专门讲。

5.2.2 样式与行为控制

TextField 提供了丰富的参数来控制外观和行为。我挑几个常用的说说:

  • label:占位提示,输入内容后会浮到上方
  • placeholder:占位文本,输入内容后消失
  • leadingIcon / trailingIcon:前后图标,比如搜索框前面的放大镜
  • visualTransformation:视觉转换,比如密码输入时显示为圆点
  • keyboardOptions:键盘类型,比如数字键盘、邮箱键盘

举个例子,一个带密码切换功能的输入框:

@Composable
fun PasswordField() {
    var password by remember { mutableStateOf("") }
    var showPassword by remember { mutableStateOf(false) }

    OutlinedTextField(
        value = password,
        onValueChange = { password = it },
        label = { Text("密码") },
        visualTransformation = if (showPassword) VisualTransformation.None
                               else PasswordVisualTransformation(),
        trailingIcon = {
            IconButton(onClick = { showPassword = !showPassword }) {
                Icon(
                    imageVector = if (showPassword) Icons.Default.VisibilityOff
                                  else Icons.Default.Visibility,
                    contentDescription = "切换密码可见"
                )
            }
        },
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
    )
}

我曾经在项目里做过一个登录页面,用户反馈说密码输入时看不到切换按钮。排查后发现是 trailingIcon 的点击区域太小,加了个 Modifier.size(48.dp) 就好了。嗯,交互细节真的很重要。

5.3 字体资源的加载

如果你需要使用自定义字体,Compose 也支持。把字体文件放到 res/font/ 目录下,然后这样加载:

val customFontFamily = FontFamily(
    Font(R.font.pingfang_regular, FontWeight.Normal),
    Font(R.font.pingfang_bold, FontWeight.Bold)
)

Text(
    text = "自定义字体",
    fontFamily = customFontFamily,
    fontWeight = FontWeight.Bold
)

我个人建议,如果项目中有多种字体粗细,最好把整个 FontFamily 定义好,而不是每个地方单独加载。这样统一管理,后期换字体也方便。

5.4 知识体系总览

下面这张图,帮你梳理本章的核心内容:

文本组件 Text(显示文本) TextField(输入文本) 字体样式 颜色设置 对齐方式 状态管理 样式控制 键盘类型 核心:通过 style 参数统一控制样式 TextField 是受控组件,必须绑定状态

5.5 避坑指南

最后,分享几个我实际项目中遇到的坑:

  • Text 不显示:检查颜色是否设置了透明度,或者父容器大小是否为0。我曾经把 Text 放在一个高度为0的 Box 里,找了半天原因。
  • TextField 输入卡顿:如果输入框内容很多,考虑用 TextFieldValue 替代 String,它可以更精细地控制光标位置和选择范围。
  • 字体文件不生效:确认字体文件放在 res/font/ 目录下,并且文件名是小写字母和下划线。Compose 对资源文件名有严格限制。

文本组件看似简单,但用好它们,能让你的 UI 体验提升一个档次。记住一点:样式统一、状态可控、交互清晰。做到这三点,你的文本组件就不会出大问题。

核心要点回顾:

  • Text 通过 style 参数控制字体、颜色、对齐
  • TextField 是受控组件,必须用 remember + mutableStateOf 管理状态
  • 自定义字体通过 FontFamily 加载,统一管理更佳
  • 对齐效果需要配合 Modifier.fillMaxWidth() 才能正确显示

公众号:蓝海资料掘金营,微信deep3321