Compose中TextField的简单使用

7/8/2021 AndroidComposeTextField

# 基础API

fun TextField(
    value: String, // 文字,也可以传入TextFieldValue
    onValueChange: (TextFieldValue) -> Unit, // 文字改变的回调
    modifier: Modifier = Modifier, // 修饰符
    enabled: Boolean = true, // 是否可用,等价于Android中的enable属性
    readOnly: Boolean = false, // 是否只读
    textStyle: TextStyle = LocalTextStyle.current, // 文字格式,可以传入SpanStyle和ParagraphStyle
    label: @Composable (() -> Unit)? = null, // 标签,跟Material中的label类似
    placeholder: @Composable (() -> Unit)? = null, // 输入文本为空的占位符,有焦点才会展示
    leadingIcon: @Composable (() -> Unit)? = null, // 头部图标
    trailingIcon: @Composable (() -> Unit)? = null, // 尾部图标
    isError: Boolean = false, // 指定当前输入文本是否出错,如果为错,则会把文字和线框显示为红色来提示
    visualTransformation: VisualTransformation = VisualTransformation.None, // 可以简单的理解为EditText中的inputType
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default, // 定义软键盘上的返回键的功能,可以定义为return/search等
    keyboardActions: KeyboardActions = KeyboardActions(), // 按下软键盘上返回键的回调
    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() // 用来定义文字,光标等的处于不同状态的颜色
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 基本用法

我们来简单实现一个搜索文本框,左边搜索按钮,点击就提示输入的关键字,右边清除按钮,点击就清除内容,大概效果如下:

目标

用Compose实现的代码如下:

@Composable
fun TextFieldDemo(context: Context) {
    // 定义一个可观测的text,用来在TextField中展示
    var text by remember {
        mutableStateOf("")
    }
    TextField(
        value = text, // 显示文本
        onValueChange = { text = it }, // 文字改变时,就赋值给text
        label = { Text(text = "Input") }, // label是Input
        // 头部图标,设置为搜索
        leadingIcon = @Composable {
            Image(
                imageVector = Icons.Filled.Search, // 搜索图标
                contentDescription = null,
                modifier = Modifier.clickable { Toast.makeText(context, "search $text", Toast.LENGTH_SHORT).show() }) // 给图标添加点击事件,点击就吐司提示内容
        },
        // 尾部图标,设置为清除
        trailingIcon = @Composable {
            Image(imageVector = Icons.Filled.Clear, // 清除图标
                contentDescription = null,
                modifier = Modifier.clickable { text = "" }) // 给图标添加点击事件,点击就清空text
        },
        placeholder = @Composable { Text(text = "This is placeholder") }, // 不输入内容时的占位符
    )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

效果如下:

实际效果

现在让我们来添加两行代码:

isError = true, // 展示错误提示
visualTransformation = PasswordVisualTransformation(), // 展示为密文
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), // 将键盘的回车键定义为搜索
// 给回车键定义点击搜索事件,弹出搜索内容
keyboardActions = KeyboardActions(onSearch = { Toast.makeText(context, "search $text", Toast.LENGTH_SHORT).show() })
singleLine = true // 重新定义回车键,一定要定义为单行,否则回车键还是换行,重定义不生效
1
2
3
4
5
6

然后看下效果:

返回键变搜索

我们看到,文字和下划线都提示为红色,表示错误,文字显示为密文字,回车键变为搜索,当然,回车键还可以定义为其他类型,比如:Go,Next,Done等,大家可以自行尝试。

现在让我们来添加形状,我们添加这样一行代码:

shape = RoundedCornerShape(16.dp) // 指定圆角矩形
1

效果如下:

加圆角

发现是圆角的了,但是却有个下划线,怎么办呢,我们可以指定colors为透明来隐藏下划线,如下:

// 指定下划线颜色
colors = TextFieldDefaults.textFieldColors(
    focusedIndicatorColor = Color.Transparent, // 有焦点时的颜色,透明
    unfocusedIndicatorColor = Color.Green, // 无焦点时的颜色,绿色
    errorIndicatorColor = Color.Red, // 错误时的颜色,红色
    disabledIndicatorColor = Color.Gray // 不可用时的颜色,灰色
)
1
2
3
4
5
6
7

我们还要修改

isError = false, // 不展示错误提示
1

不然下划线就一直是红色的了。好,我们来看效果:

修改下划线颜色

我们看到,当没有焦点时,下划线为绿色,有焦点就看不到了(因为透明),如果想要去掉下划线,可以直接把所有状态下的下划线颜色都设为透明,至于错误和不可用时下划线的颜色,大家可以自行尝试看下效果。

# 扩展

# 1 轮廓式文本框OutlinedTextField

轮廓式文本框OutlinedTextField自带轮廓,也就是只提供描边,可以轻易实现产品和UI眼里的效果,我们来简单写个demo:

@Composable
fun OutlinedTextFieldDemo() {
    var text by remember { mutableStateOf("") }
    OutlinedTextField(value = text,
        label = { Text(text = "Input something") },
        onValueChange = { text = it })
}
1
2
3
4
5
6
7

很简单,API跟TextField都一样的,只是样式不同而已,效果如下:

轮廓式文本框

# 2 基本文本框BasicTextField

BasicTextField可以用来响应硬件或软件盘编辑文字,可以自定义cursor、边框等,但是没有placeholder和label属性。API如下:

fun BasicTextField(
    value: String, // 文字,也可以传入TextFieldValue
    onValueChange: (String) -> Unit, // 文字改变的回调
    modifier: Modifier = Modifier, // 修饰符
    enabled: Boolean = true, // 是否可用
    readOnly: Boolean = false, // 是否只读
    textStyle: TextStyle = TextStyle.Default, // 文字样式
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default, // 定义软键盘上的返回键的功能,可以定义为return/search等
    keyboardActions: KeyboardActions = KeyboardActions.Default, // 按下软键盘上返回键的回调
    singleLine: Boolean = false, // 是否是单行
    maxLines: Int = Int.MAX_VALUE, // 最大行数
    visualTransformation: VisualTransformation = VisualTransformation.None, // 可以简单的理解为EditText中的inputType
    onTextLayout: (TextLayoutResult) -> Unit = {}, // 布局变化的回调
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, // 表示一个由组件发出的交互流
    cursorBrush: Brush = SolidColor(Color.Black), // 重点!!画刷
    decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit = // 用来定义装饰框,innerTextField这个参数就是用来绘制文字的
        @Composable { innerTextField -> innerTextField() }
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

我们来写个小demo看下:

@Composable
fun BasicTextFieldDemo() {
    var text by remember { mutableStateOf("hello") }
    BasicTextField(
        value = text,
        onValueChange = { text = it },
    )
}
1
2
3
4
5
6
7
8

展示效果如下:

轮廓式文本框

就一个hello...,没有边框,如果你初始值是空,连字都看不到,就是个空白,真是够原始,够基础,确实Basic,现在我们加个背景吧,添加:

modifier = Modifier.background(Color.Green, RoundedCornerShape(8.dp)) // 加一个绿色背景
1

效果如下:

轮廓式文本框

确实是个绿色背景...,我们来试着加个文本框,添加如下代码

// 画修饰框
decorationBox = @Composable { innerTextField ->
    // 先画个圆压压惊
    Canvas(modifier = Modifier.size(width = 100.dp, height = 50.dp)) {
        drawCircle(color = Color.Red, style = Stroke(width = 1F))
    }
    // 然后再画文字
    innerTextField()
}
1
2
3
4
5
6
7
8
9

这个其实很简单,可以理解为先绘制一个圆形,然后调用innerTextField()绘制原有的文字,效果如下:

轮廓式文本框

# 总结

如果你想完全自定义文本框,可以使用BasicTextField;

如果你想使用轮廓式文本框,使用OutlinedTextField;

如果你想使用实心文本框,使用TextField即可;

其中TextField和OutlinedTextField除了一个是实心,一个是空心,其他API都是一样的,而BasicTextField则完全是自定义的。

完整代码点: 这里 (opens new window)

Last Updated: 1/28/2022, 4:13:43 PM