《Jetpack Compose系列学习》-7 Compose的简单控件之TextField

输入和修改文字

在Compose中TextField允许用户输入和修改文字,同Android中的EditText。TextField实现有两个:TextField 和 BasicTextField。

  1. 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重组,并更新控件状态,我们来看看效果:

image.png

我们再看看OutlinedTextField

Column {
    val text = remember {
        mutableStateOf("你好")
    }
    OutlinedTextField(
        value = text.value,
        onValueChange = {text.value = it},
        label = { Text("") }
    )
}
复制代码
  1. 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("标签") }
    )
}
复制代码

image.png

可以看到OutlinedTextField和TextField的使用方法基本一致,只是多了一个外边框而已。

  1. BasicTextField

BasicTextField允许用户通过软键盘或者硬键盘编辑文字,但是没有提供提示或占位符等装饰,用法如下:

Column {
    val text = remember {
        mutableStateOf("你好")
    }
    BasicTextField(
        value = text.value,
        onValueChange = {text.value = it}
    )
}
复制代码

image.png

使用方法都差不多,但是看起来不那么美观,但是我们可以通过属性去设置的更美观些。

显示样式

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)
    )
}
复制代码

image.png

我们看文字最多只能输入两行,还有文字的样式。

键盘选项

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,运行结果如图:

image.png

那么我们如何监听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)
    )
}
复制代码

点击后看效果:

image.png

我们看到了弹出了toast,我们通过LocalContext.current来获取上下文context,大家以后也可以这么获取Context来进行使用。后续会继续学习其他的控件。相关代码已上传到github github.com/Licarey/com… ,欢迎点赞。

猜你喜欢

转载自juejin.im/post/7079265116306276359
今日推荐