输入和修改文字
在Compose中TextField允许用户输入和修改文字,同Android中的EditText。TextField实现有两个:TextField 和 BasicTextField。
- TextField
TextField是Material Design实现,默认样式为填充,OutlinedTextField是有轮廓样式。 我们先看看TextField的使用:
// TextField用法
val text = remember {
mutableStateOf("你好")
}
TextField(
value = text.value,
onValueChange = {text.value = it},
label = { Text("标签") }
)
复制代码
我们知道,将State中的String传值给TextField中的value,当TextField中输入文本时,onValueChange会将值赋给State,当State发生改变时触发Compose重组,并更新控件状态,我们来看看效果:
我们再看看OutlinedTextField
Column {
val text = remember {
mutableStateOf("你好")
}
OutlinedTextField(
value = text.value,
onValueChange = {text.value = it},
label = { Text("") }
)
}
复制代码
- OutlinedTextField
Column {
val text = remember {
mutableStateOf("你好")
}
OutlinedTextField(
value = text.value,
onValueChange = {text.value = it},
modifier = Modifier
.fillMaxWidth()
.background(Color.Red)
.padding(15.dp),
label = { Text("标签") }
)
}
复制代码
可以看到OutlinedTextField和TextField的使用方法基本一致,只是多了一个外边框而已。
- BasicTextField
BasicTextField允许用户通过软键盘或者硬键盘编辑文字,但是没有提供提示或占位符等装饰,用法如下:
Column {
val text = remember {
mutableStateOf("你好")
}
BasicTextField(
value = text.value,
onValueChange = {text.value = it}
)
}
复制代码
使用方法都差不多,但是看起来不那么美观,但是我们可以通过属性去设置的更美观些。
显示样式
TextField和BasicTextField的参数基本一致,我们可以通过TextField为例来看看一些属性的用法,我们来看看它的源码:
@Composable
fun TextField(
value: String, // 文字
onValueChange: (String) -> Unit, // 监听输入
modifier: Modifier = Modifier, // 修饰符
enabled: Boolean = true, // 是否可点击
readOnly: Boolean = false, // 是否只读
textStyle: TextStyle = LocalTextStyle.current, // 文字样式
label: @Composable (() -> Unit)? = null, // 显示在文本容器内的可选标签
placeholder: @Composable (() -> Unit)? = null, // 占位符
leadingIcon: @Composable (() -> Unit)? = null, // 文本容器开头的可选icon
trailingIcon: @Composable (() -> Unit)? = null, // 文本容器结尾的可选icon
isError: Boolean = false, // 指示文字的当前内容是否错误
visualTransformation: VisualTransformation = VisualTransformation.None, // 转换输入value的可视表示形式
keyboardOptions: KeyboardOptions = KeyboardOptions.Default, // 软键盘配置项
keyboardActions: KeyboardActions = KeyboardActions(), // 输入完成后的IME操作回调,如“回车发送”
singleLine: Boolean = false, // 是否是单行显示
maxLines: Int = Int.MAX_VALUE, // 最大行数
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, // 由组件发出的交互流
shape: Shape =
MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize), // 文本容器的形状
colors: TextFieldColors = TextFieldDefaults.textFieldColors() // 光标不同状态下文本颜色
) {
// 省略...
}
复制代码
里面有一部分参数我们在Text中已经熟悉了,我们挑几个常用的参数了解下其用法。
Column {
val text = remember {
mutableStateOf("你好")
}
TextField(
value = text.value,
onValueChange = {text.value = it},
label = { Text("Enter text") },
maxLines = 2,
textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
modifier = Modifier.padding(15.dp).background(Color.Red)
)
}
复制代码
我们看文字最多只能输入两行,还有文字的样式。
键盘选项
Android View中的EditText是通过inputType来设置输入类型的,而TextField是通过keyboardOptions参数,它的类型是KeyboardOptions,我么来看看它的源码:
@Immutable
class KeyboardOptions constructor(
val capitalization: KeyboardCapitalization = KeyboardCapitalization.None,
val autoCorrect: Boolean = true,
val keyboardType: KeyboardType = KeyboardType.Text,
val imeAction: ImeAction = ImeAction.Default
) {
companion object {
/**
* 默认选项
*/
val Default = KeyboardOptions()
}
// 省略...
}
复制代码
capitalization参数类型是KeyboardCapitalization,用来请求软键盘大写文本的选项。其默认值是KeyboardCapitalization.None。其它的类型有:
companion object {
/**
* 不自动大写文本
*/
val None = KeyboardCapitalization(0)
/**
* 所有字符大写
*/
val Characters = KeyboardCapitalization(1)
/**
* 每个单词的第一个字符大写
*/
val Words = KeyboardCapitalization(2)
/**
* 每个句子的第一个字符大写
*/
val Sentences = KeyboardCapitalization(3)
}
复制代码
autoCorrect参数类型是Boolean, 默认状态是true,是通知键盘是否启用自动更正,这里需要注意,autoCorrect仅适用于基于文本的keyboardType,如KeyboardType.Email、KeyboardType.Uri,不适用于KeyboardType.Number。
keyboardType参数类型为KeyboardType,是文本字段中使用的键盘类型,来看看有哪几种类型:
companion object {
/**
* 常规键盘的IME的键盘类型
*/
val Text: KeyboardType = KeyboardType(1)
/**
* 能够输入ASCII字符的IME
*/
val Ascii: KeyboardType = KeyboardType(2)
/**
* 输入数字类型的IME
*/
val Number: KeyboardType = KeyboardType(3)
/**
* 输入电话号码的IME
*/
val Phone: KeyboardType = KeyboardType(4)
/**
* 输入Uri的IME
*/
val Uri: KeyboardType = KeyboardType(5)
/**
* 输入电子邮箱的IME
*/
val Email: KeyboardType = KeyboardType(6)
/**
* 输入密码的IME
*/
val Password: KeyboardType = KeyboardType(7)
/**
* 输入数字密码的IME
*/
val NumberPassword: KeyboardType = KeyboardType(8)
}
复制代码
开发中可以根据对应的业务去设置对应的输入类型。
imeAction参数类型是ImeAction,默认是ImeAction.Default,表示键盘会指定IME操作,并且可能会在键盘上显示特定的图标,如指定了ImeAction.Search,则可能会显示一个搜索图标,我们来看看ImeAction的源码,其伴生对象里定义了几种ImeAction类型:
companion object {
/**
* 默认,让键盘来决定操作
*/
val Default: ImeAction = ImeAction(1)
/**
* 不执行任何操作,默认为换行的动作
*/
val None: ImeAction = ImeAction(0)
/**
* 表示用户想转到输入的文本目标,即访问URL
*/
val Go: ImeAction = ImeAction(2)
/**
* 表示用户执行搜索,即网络搜索查询
*/
val Search: ImeAction = ImeAction(3)
/**
* 用户要在输入中发送文本,即SMS
*/
val Send: ImeAction = ImeAction(4)
/**
* 用户想返回先前的输入,即返回表格中的先前字段
*/
val Previous: ImeAction = ImeAction(5)
/**
* 用户已完成当前输入,并且想要移至下一个字段
*/
val Next: ImeAction = ImeAction(6)
/**
* 用户已完成输入操作,现在应该发生某种终结行为
*/
val Done: ImeAction = ImeAction(7)
}
复制代码
同KeyboardCapitalization和KeyboardType一样,在里面伴生对象中定义了几种类型,可以根据具体业务需求,使用对应的类型。
我们看一个例子:
Column {
val text = remember {
mutableStateOf("你好")
}
TextField(
value = text.value,
onValueChange = {text.value = it},
label = { Text("Enter text") },
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Characters, // 全部字符大写
keyboardType = KeyboardType.Email, // 输入email
autoCorrect = true, // 自动纠正
imeAction = ImeAction.Search // IME动作设置为搜索
),
textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
modifier = Modifier.padding(15.dp).background(Color.Red)
)
}
复制代码
我们添加了KeyboardOptions,设置全部字符大写,键盘类型是KeyboardType.Email,并开启了自动更正,IME动作设置为ImeAction.Search,运行结果如图:
那么我们如何监听ImeAction并执行呢?就是KeyboardActions参数,里面有几种类型:
class KeyboardActions(
/**
* 用户触发ImeAction.Done操作时,执行该命令
*/
val onDone: (KeyboardActionScope.() -> Unit)? = null,
/**
* 用户触发ImeAction.Go操作时,执行该命令
*/
val onGo: (KeyboardActionScope.() -> Unit)? = null,
/**
* 用户触发ImeAction.Next操作时,执行该命令,空值表示应执行默认实现
*/
val onNext: (KeyboardActionScope.() -> Unit)? = null,
/**
* 用户触发ImeAction.Previous操作时,执行该命令,空值表示应执行默认实现
*/
val onPrevious: (KeyboardActionScope.() -> Unit)? = null,
/**
* 用户触发ImeAction.Search操作时,执行该命令
*/
val onSearch: (KeyboardActionScope.() -> Unit)? = null,
/**
* 用户触发ImeAction.Send操作时,执行该命令
*/
val onSend: (KeyboardActionScope.() -> Unit)? = null
) {
companion object {
/**
* 不指定任何操作
*/
val Default: KeyboardActions = KeyboardActions()
}
}
复制代码
我们可以看到KeyboardActions是一个普通类,在构造方法中有6个参数,分别和ImeAction中的6个类型一一对应,所以如果设置了ImeAction,就需要实现对应的KeyboardActions来执行对应的操作。我们在上面的代码基础上添加KeyboardActions的代码:
Column {
val context = LocalContext.current
val text = remember {
mutableStateOf("你好")
}
TextField(
value = text.value,
onValueChange = {text.value = it},
label = { Text("Enter text") },
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Characters, // 全部字符大写
keyboardType = KeyboardType.Email, // 输入email
autoCorrect = true, // 自动纠正
imeAction = ImeAction.Search // IME动作设置为搜索
),
keyboardActions = KeyboardActions(
onSearch = {
Toast.makeText(context, "点击了Search", Toast.LENGTH_LONG).show()
}
),
textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
modifier = Modifier.padding(15.dp).background(Color.Red)
)
}
复制代码
点击后看效果:
我们看到了弹出了toast,我们通过LocalContext.current来获取上下文context,大家以后也可以这么获取Context来进行使用。后续会继续学习其他的控件。相关代码已上传到github github.com/Licarey/com… ,欢迎点赞。