写点什么

Jetpack Composes 之 TextField 详解

作者:坚果
  • 2022 年 6 月 05 日
  • 本文字数:5741 字

    阅读完需:约 19 分钟

TextField

@Composablefun 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,    trailingIcon: @Composable (() -> Unit)? = null,    isError: Boolean = false,    visualTransformation: VisualTransformation = VisualTransformation.None,    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,    keyboardActions: KeyboardActions = KeyboardActions(),    singleLine: Boolean = false,    maxLines: Int = Int.MAX_VALUE,    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },    shape: Shape =        MaterialTheme.shapes.small.  (bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),    colors: TextFieldColors = TextFieldDefaults.textFieldColors())
复制代码


Material Design filled text field


Filled TextFieldOutlined TextField 有更多的视觉效果,可以让它们在被其他内容和组件包围时显得更加突出。

注意

Filled TextFieldOutlined TextField 都是按照 Material Design 来设计的,所以里面的一些间距是固定的,当你使用 Modifier.size() 等之类的方法尝试去修改它很可能会有以下的效果


TextField(    value = text,    onValueChange = {        text = it    },    modifier = Modifier.height(20.dp))
复制代码



如果你想自定义一个 TextField 的高度,以及其他的自定义效果,你应该使用 BasicTextField


一个简单的 TextField 使用的例子是这样的:


import androidx.compose.runtime.*
@Composablefun TextFieldDemo() { var text by remember{ mutableStateOf("")}
TextField( value = text, onValueChange = { text = it } )}
复制代码


1. singleLine 参数

使用 singleLine 参数可以将 TextField 设置成只有一行


设置了 singleLine 再设置 maxLines 将无效


@Composablefun TextFieldDemo() {    var text by remember{ mutableStateOf("")}
TextField( value = text, onValueChange = { text = it }, singleLine = true )}
复制代码

2. label 参数

label 标签可以运用在 TextField 中,当聚焦的时候会改变字体大小


@Composablefun TextFieldDemo() {    var text by remember{ mutableStateOf("")}
Column( modifier = Modifier .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { TextField( value = text, onValueChange = { text = it }, singleLine = true, label = { Text("邮箱") } ) }}
复制代码


3. leadingIcon 参数

leadingIcon 参数可以在 TextField 前面布置 lambda 表达式所接收到的东西


TextField(    value = text,    onValueChange = {        text = it    },    leadingIcon = {        Icon(Icons.Filled.Search, null)    },)
复制代码



虽然名字上叫做 leadingIcon,但是 leadingIcon 接收来自一个 @Composable 函数的 lambda 表达式,


我们也可以在里面填入 Text 函数


TextField(    value = text,    onValueChange = {        text = it    },    leadingIcon = {        Text("联系人")    },)
复制代码


4. trailingIcon 参数

trailingIcon 参数可以在 TextField 尾部布置 lambda 表达式所接收到的东西


TextField(    value = text,    onValueChange = {        text = it    },    trailingIcon = {        Text("@163.com")    },)
复制代码



trailingIcon = {    IconButton(onClick = {            }){        Icon(Icons.Filled.Send, null)    }},
复制代码


5. Color 参数

@Composablefun textFieldColors(    // 输入的文字颜色    textColor: Color = LocalContentColor.current.  (LocalContentAlpha.current),
// 禁用 TextField 时,已有的文字颜色 disabledTextColor: Color = textColor. (ContentAlpha.disabled),
// 输入框的背景颜色,当设置为 Color.Transparent 时,将透明 backgroundColor: Color = MaterialTheme.colors.onSurface. (alpha = BackgroundOpacity),
// 输入框的光标颜色 cursorColor: Color = MaterialTheme.colors.primary,
// 当 TextField 的 isError 参数为 true 时,光标的颜色 errorCursorColor: Color = MaterialTheme.colors.error,
// 当输入框处于焦点时,底部指示器的颜色 focusedIndicatorColor: Color = MaterialTheme.colors.primary. (alpha = ContentAlpha.high),
// 当输入框不处于焦点时,底部指示器的颜色 unfocusedIndicatorColor: Color = MaterialTheme.colors.onSurface. (alpha = UnfocusedIndicatorLineOpacity),
// 禁用 TextField 时,底部指示器的颜色 disabledIndicatorColor: Color = unfocusedIndicatorColor. (alpha = ContentAlpha.disabled),
// 当 TextField 的 isError 参数为 true 时,底部指示器的颜色 errorIndicatorColor: Color = MaterialTheme.colors.error,
// TextField 输入框前头的颜色 leadingIconColor: Color = MaterialTheme.colors.onSurface. (alpha = IconOpacity),
// 禁用 TextField 时 TextField 输入框前头的颜色 disabledLeadingIconColor: Color = leadingIconColor. (alpha = ContentAlpha.disabled),
// 当 TextField 的 isError 参数为 true 时 TextField 输入框前头的颜色 errorLeadingIconColor: Color = leadingIconColor,
// TextField 输入框尾部的颜色 trailingIconColor: Color = MaterialTheme.colors.onSurface. (alpha = IconOpacity),
// 禁用 TextField 时 TextField 输入框尾部的颜色 disabledTrailingIconColor: Color = trailingIconColor. (alpha = ContentAlpha.disabled),
// 当 TextField 的 isError 参数为 true 时 TextField 输入框尾部的颜色 errorTrailingIconColor: Color = MaterialTheme.colors.error,
// 当输入框处于焦点时,Label 的颜色 focusedLabelColor: Color = MaterialTheme.colors.primary. (alpha = ContentAlpha.high),
// 当输入框不处于焦点时,Label 的颜色 unfocusedLabelColor: Color = MaterialTheme.colors.onSurface. (ContentAlpha.medium),
// 禁用 TextField 时,Label 的颜色 disabledLabelColor: Color = unfocusedLabelColor. (ContentAlpha.disabled),
// 当 TextField 的 isError 参数为 true 时,Label 的颜色 errorLabelColor: Color = MaterialTheme.colors.error,
// Placeholder 的颜色 placeholderColor: Color = MaterialTheme.colors.onSurface. (ContentAlpha.medium),
// 禁用 TextField 时,placeholder 的颜色 disabledPlaceholderColor: Color = placeholderColor. (ContentAlpha.disabled))
复制代码


调用方法


TextField(    value = text,    onValueChange = {        text = it    },    leadingIcon = {        Icon(Icons.Filled.Search, null)    },    colors = TextFieldDefaults.textFieldColors(        textColor = Color(0xFF0079D3),        backgroundColor = Color.Transparent    ))
复制代码



在你使用 IDE 智能补全的时候可能遇到这种情况



解决方法如下,手动打完函数名


6. visualTransformation 参数

visualTransformation 可以帮助我们应用输入框的显示模式


var text by remember{mutableStateOf("")}var passwordHidden by remember{ mutableStateOf(false)}
TextField( value = text, onValueChange = { text = it }, trailingIcon = { IconButton( onClick = { passwordHidden = !passwordHidden } ){ Icon(painterResource(id = R.drawable.visibility), null) } }, label = { Text("密码") }, visualTransformation = if(passwordHidden) PasswordVisualTransformation() else VisualTransformation.None)
复制代码


BasicTextField

@Composablefun BasicTextField(  value: String,  onValueChange: (String) -> Unit,  modifier: Modifier = Modifier,  enabled: Boolean = true,  readOnly: Boolean = false,  textStyle: TextStyle = TextStyle.Default,  keyboardOptions: KeyboardOptions = KeyboardOptions.Default,  keyboardActions: KeyboardActions = KeyboardActions.Default,  singleLine: Boolean = false,  maxLines: Int = Int.MAX_VALUE,  visualTransformation: VisualTransformation = VisualTransformation.None,  onTextLayout: (TextLayoutResult) -> Unit = {},  // 当输入框内文本触发更新时候的回调,包括了当前文本的各种信息  interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },  cursorBrush: Brush = SolidColor(Color.Black),  // 输入框光标的颜色  decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =    @Composable { innerTextField -> innerTextField() }  // 是一个允许在 TextField 周围添加修饰的 @Composable lambda  // 我们需要在布局中调用 innerTextField() 才能完成 TextField 的构建)
复制代码


使用 BasicTextField 可以让你拥有更高的自定义效果

1. 简单使用

一个简单的使用例子如下:


var text by remember { mutableStateOf("") }
Box( modifier = Modifier .fillMaxSize() .background(Color(0xFFD3D3D3)), contentAlignment = Alignment.Center) { BasicTextField( value = text, onValueChange = { text = it }, modifier = Modifier .background(Color.White, CircleShape) .height(35.dp) .fillMaxWidth(), decorationBox = { innerTextField -> Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(horizontal = 10.dp) ) { IconButton( onClick = { } ) { Icon(painterResource(id = R.drawable.mood), null) } Box( modifier = Modifier.weight(1f), contentAlignment = Alignment.CenterStart ) { innerTextField() } IconButton( onClick = { }, ) { Icon(Icons.Filled.Send, null) } } } )}
复制代码



在刚才的例子中,我们在 decorationBox 里面写了很多布局组件,最后通过调用一次 innerTextFiled() 来完成输入框的构建。

2. 其他效果


代码查看:


var text by remember { mutableStateOf("") }
Box( modifier = Modifier .fillMaxSize() .background(Color(0xFFD3D3D3)), contentAlignment = Alignment.Center) { BasicTextField( value = text, onValueChange = { text = it }, modifier = Modifier .background(Color.White) .fillMaxWidth(), decorationBox = { innerTextField -> Column( modifier = Modifier.padding(vertical = 10.dp) ) { Row( verticalAlignment = Alignment.CenterVertically, ) { IconButton(onClick = {}) { Icon(painterResource(id = R.drawable.mood), contentDescription = null) } IconButton(onClick = {}) { Icon(painterResource(id = R.drawable.gif), contentDescription = null) } IconButton(onClick = {}) { Icon(painterResource(id = R.drawable.shortcut), contentDescription = null) } IconButton(onClick = {}) { Icon(painterResource(id = R.drawable.more), contentDescription = null) } } Box( modifier = Modifier.padding(horizontal = 10.dp) ) { innerTextField() } Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { TextButton(onClick = { /*TODO*/ }) { Text("发送") } Spacer(Modifier.padding(horizontal = 10.dp)) TextButton(onClick = { /*TODO*/ }) { Text("关闭") } } } } )}
复制代码

更多

TextField 参数详情


[BasicTextField 参数详情](

发布于: 刚刚阅读数: 3
用户头像

坚果

关注

此间若无火炬,我便是唯一的光 2020.10.25 加入

公众号:“大前端之旅”,华为云享专家,InfoQ签约作者,51CTO博客首席体验官,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。

评论

发布
暂无评论
Jetpack Composes 之TextField详解_6月月更_坚果_InfoQ写作社区