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
其他资源
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- 构建 Compose 界面
- 状态和 Jetpack Compose
- 在 Compose 中保存界面状态