TextField
允许用户输入和修改文本。您可以使用两种类型的文本字段:基于状态的文本字段和基于值的文本字段。选择您要显示内容的类型
我们建议使用基于状态的文本字段,因为它们提供了一种更完整、更可靠的 TextField
状态管理方法。下表概述了这些文本字段类型之间的差异,并包含基于状态的文本字段提供的主要优势
功能 |
基于值的文本字段 |
基于状态的文本字段 |
基于状态的优势 |
---|---|---|---|
状态管理 |
使用 |
明确使用 |
|
视觉转换 |
使用 |
使用 |
|
行限制 |
接受 |
使用 |
|
安全文本字段 |
不适用 |
|
|
本页面介绍了如何实现 TextField
、设置 TextField
输入的样式以及配置其他 TextField
选项,例如键盘选项和视觉转换用户输入。
选择 TextField
实现
TextField
实现有两级
TextField
是 Material Design 实现。我们建议您选择此实现,因为它遵循 Material Design 指南BasicTextField
允许用户通过硬件或软件键盘编辑文本,但不提供提示或占位符等修饰。
TextField( state = rememberTextFieldState(initialText = "Hello"), label = { Text("Label") } )
OutlinedTextField( state = rememberTextFieldState(), label = { Text("Label") } )
设置 TextField
样式
TextField
和 BasicTextField
共享许多常见的自定义参数。TextField
的完整列表可在 TextField
源代码中找到。这是一个非详尽的有用参数列表
textStyle
lineLimits
TextField( state = rememberTextFieldState("Hello\nWorld\nInvisible"), lineLimits = TextFieldLineLimits.MultiLine(maxHeightInLines = 2), placeholder = { Text("") }, textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold), label = { Text("Enter text") }, modifier = Modifier.padding(20.dp) )
当您的设计需要 Material TextField
或 OutlinedTextField
时,我们建议使用 TextField
而非 BasicTextField
。但是,在构建不需要 Material 规范中修饰的设计时,应使用 BasicTextField
。
使用 Brush API 设置输入样式
您可以使用 Brush API 在 TextField
中进行更高级的样式设置。以下部分介绍了如何使用画笔为 TextField
输入添加彩色渐变。
有关使用 Brush API 设置文本样式的更多信息,请参阅使用 Brush API 启用高级样式设置。
使用 TextStyle
实现彩色渐变
要在 TextField
中实现随输入变化的彩色渐变,请将您选择的画笔设置为 TextField
的 TextStyle
。在此示例中,我们使用带有 linearGradient
的内置画笔,以便在文本输入 TextField
时查看彩虹渐变效果。
val brush = remember { Brush.linearGradient( colors = listOf(Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Magenta) ) } TextField( state = rememberTextFieldState(), textStyle = TextStyle(brush = brush) )

TextField
内容的彩虹渐变效果。管理文本字段状态
TextField
使用一个名为 TextFieldState
的专用状态持有者类来管理其内容和当前选择。TextFieldState
旨在提升到您架构中适合的任何位置。TextFieldState
提供 2 个主要属性
initialText
:TextField
的内容。initialSelection
:指示光标或选择的当前位置。
TextFieldState
与其他方法(如 onValueChange
回调)的区别在于,TextFieldState
完全封装了整个输入流程。这包括使用正确的后端数据结构、内联过滤器和格式化程序,以及同步来自不同来源的所有编辑。
您可以使用 TextFieldState()
在 TextField
中提升状态。为此,我们建议使用 rememberTextFieldState()
函数。rememberTextFieldState()
在您的可组合项中创建 TextFieldState
实例,确保状态对象被记住,并提供内置的保存和恢复功能
val usernameState = rememberTextFieldState() TextField( state = usernameState, lineLimits = TextFieldLineLimits.SingleLine, placeholder = { Text("Enter Username") } )
rememberTextFieldState
可以有空白参数,也可以传入初始值来表示文本的初始值。如果在后续重组中传入不同的值,则状态的值不会更新。要在初始化后更新状态,请调用 TextFieldState
上的编辑方法。
TextField( state = rememberTextFieldState(initialText = "Username"), lineLimits = TextFieldLineLimits.SingleLine, )

TextField
。使用 TextFieldBuffer
修改文本
TextFieldBuffer
用作可编辑文本容器,功能类似于 StringBuilder
。它同时包含文本内容和有关当前选择的信息。
您经常会在函数(如 TextFieldState.edit
、InputTransformation.transformInput
或 OutputTransformation.transformOutput
)中将 TextFieldBuffer
作为接收器范围。在这些函数中,您可以根据需要读取或更新 TextFieldBuffer
。之后,这些更改要么提交到 TextFieldState
,要么在 OutputTransformation
的情况下传递到渲染管道。
您可以使用标准编辑函数(如 append
、insert
、replace
或 delete
)修改缓冲区内容。要更改选择状态,可以直接设置其 selection: TextRange
变量,或使用实用函数(如 placeCursorAtEnd
或 selectAll
)。选择本身由 TextRange
表示,其中起始索引是包含的,结束索引是排他的。起始和结束值相同的 TextRange
(例如 (3, 3)
)表示光标位置,当前没有选择任何字符。
val phoneNumberState = rememberTextFieldState() LaunchedEffect(phoneNumberState) { phoneNumberState.edit { // TextFieldBuffer scope append("123456789") } } TextField( state = phoneNumberState, inputTransformation = InputTransformation { // TextFieldBuffer scope if (asCharSequence().isDigitsOnly()) { revertAllChanges() } }, outputTransformation = OutputTransformation { if (length > 0) insert(0, "(") if (length > 4) insert(4, ")") if (length > 8) insert(8, "-") } )
编辑 TextFieldState
中的文本
有几种方法允许您通过状态变量直接编辑状态
edit
:允许您编辑状态内容,并为您提供TextFieldBuffer
函数,以便您可以使用insert
、replace
、append
等方法。val usernameState = rememberTextFieldState("I love Android") // textFieldState.text : I love Android // textFieldState.selection: TextRange(14, 14) usernameState.edit { insert(14, "!") } // textFieldState.text : I love Android! // textFieldState.selection: TextRange(15, 15) usernameState.edit { replace(7, 14, "Compose") } // textFieldState.text : I love Compose! // textFieldState.selection: TextRange(15, 15) usernameState.edit { append("!!!") } // textFieldState.text : I love Compose!!!! // textFieldState.selection: TextRange(18, 18) usernameState.edit { selectAll() } // textFieldState.text : I love Compose!!!! // textFieldState.selection: TextRange(0, 18)
setTextAndPlaceCursorAtEnd
:清除当前文本,用给定文本替换,并将光标设置在末尾。usernameState.setTextAndPlaceCursorAtEnd("I really love Android") // textFieldState.text : I really love Android // textFieldState.selection : TextRange(21, 21)
clearText
:清除所有文本。usernameState.clearText() // textFieldState.text : // textFieldState.selection : TextRange(0, 0)
有关其他 TextFieldState
函数,请参阅 TextFieldState
参考。
修改用户输入
以下部分介绍了如何修改用户输入。输入转换允许您在用户输入时过滤 TextField
输入,而输出转换在用户输入显示在屏幕上之前对其进行格式化。
使用输入转换过滤用户输入
输入转换允许您过滤用户的输入。例如,如果您的 TextField
接收美国电话号码,您只想接受 10 位数字。InputTransformation
的结果保存在 TextFieldState
中。
对于常见的 InputTransformation
用例,有内置的过滤器。要限制长度,请调用 InputTransformation.maxLength()
TextField( state = rememberTextFieldState(), lineLimits = TextFieldLineLimits.SingleLine, inputTransformation = InputTransformation.maxLength(10) )
自定义输入转换
InputTransformation
是一个单一函数接口。实现自定义 InputTransformation
时,您需要重写 TextFieldBuffer.transformInput
class CustomInputTransformation : InputTransformation { override fun TextFieldBuffer.transformInput() { } }
对于电话号码,添加一个自定义输入转换,只允许数字输入到 TextField
中
class DigitOnlyInputTransformation : InputTransformation { override fun TextFieldBuffer.transformInput() { if (!TextUtils.isDigitsOnly(asCharSequence())) { revertAllChanges() } } }
链式输入转换
要在文本输入上添加多个过滤器,请使用 then
扩展函数链式连接 InputTransformation
。过滤器按顺序执行。最佳实践是,首先应用最严格的过滤器,以避免对最终将被过滤掉的数据进行不必要的转换。
TextField( state = rememberTextFieldState(), inputTransformation = InputTransformation.maxLength(6) .then(CustomInputTransformation()), )
添加输入转换后,TextField
输入最多接受 10 位数字。
在显示之前格式化输入
OutputTransformation
允许您在用户输入渲染到屏幕上之前对其进行格式化。与 InputTransformation
不同,通过 OutputTransformation
完成的格式化不会保存在 TextFieldState
中。以上一个电话号码示例为例,您需要在适当位置添加括号和破折号

这是处理基于值的 TextField
中 VisualTransformation
的更新方法,主要区别在于您无需计算其偏移映射。
OutputTransformation
是一个单一抽象方法接口。为了实现自定义 OutputTransformation
,您需要重写 transformOutput
方法
class CustomOutputTransformation : OutputTransformation { override fun TextFieldBuffer.transformOutput() { } }
要格式化电话号码,请在您的 OutputTransformation
中,在索引 0 处添加一个左括号,在索引 4 处添加一个右括号,在索引 8 处添加一个破折号
class PhoneNumberOutputTransformation : OutputTransformation { override fun TextFieldBuffer.transformOutput() { if (length > 0) insert(0, "(") if (length > 4) insert(4, ")") if (length > 8) insert(8, "-") } }
接下来,将您的 OutputTransformation
添加到 TextField
TextField( state = rememberTextFieldState(), outputTransformation = PhoneNumberOutputTransformation() )
转换如何协同工作
下图显示了从文本输入到转换再到输出的流程

- 从输入源接收输入。
- 输入通过
InputTransformation
进行过滤,并保存在 TextFieldState 中。 - 输入通过
OutputTransformation
进行格式化。 - 输入呈现在
TextField
中。
设置键盘选项
TextField
允许您设置键盘配置选项,例如键盘布局,或在键盘支持的情况下启用自动更正。如果软件键盘不符合此处提供的选项,某些选项可能无法保证。以下是支持的键盘选项列表
capitalization(大小写)
autoCorrect(自动更正)
keyboardType(键盘类型)
imeAction(IME 操作)
其他资源
为您推荐
- 注意:禁用 JavaScript 时会显示链接文本
- 构建您的 Compose UI 架构
- 状态与 Jetpack Compose
- 在 Compose 中保存 UI 状态