Jetpack Compose:自定义 TextField 设计

nba*_*man 7 android android-textinputlayout android-jetpack android-jetpack-compose

一般来说,Jetpack Compose 中的大多数组件似乎都非常容易定制。

但是,对于TextField. 例如,假设我想做这样的事情:

自定义文本输入

人们会认为简单地包装BaseTextField会起作用。不过貌似BaseTextField组件有bug ,我开了个issue。在重新渲染组件之前,此错误将不允许用户在焦点远离文本字段后聚焦文本字段。

引用这一点,我尝试自定义OutlinedTextFieldTextField组件,但无法自定义它们以看起来像上图。如果不是因为光标颜色使用了该activeColor属性,我可以让它工作。

创建一个类似上面的可用文本字段的正确解决方法是什么?

Gab*_*tti 11

有了1.0.x你可以使用TextField

  • 删除标签 label = null
  • 将自定义颜色与TextFieldDefaults.textFieldColors参数一起应用以隐藏指标。
  • 添加onValueChange一个函数来修复这里描述的最大字符数

最后使用aColumn添加2个Textcomposables完成外部标签和计数器文本。

就像是:

var text by remember { mutableStateOf("") }
val maxChar = 5

Column(){
    //External label
    Text(
        text = "Label",
        modifier = Modifier.fillMaxWidth(),
        textAlign = TextAlign.Start,
        color = Blue
    )

    TextField(
        value = text,
        onValueChange = {
            if (it.length <= maxChar) text = it
        },
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 4.dp),
        shape = RoundedCornerShape(8.dp),
        trailingIcon = {
            Icon(Icons.Filled.Add, "", tint = Blue)
        },
        colors = TextFieldDefaults.textFieldColors(
            backgroundColor = ....,
            focusedIndicatorColor =  Color.Transparent, //hide the indicator
            unfocusedIndicatorColor = .....)
    )
    //counter message
    Text(
        text = "${text.length} / $maxChar",
        textAlign = TextAlign.End,
        color = Blue,
        style = MaterialTheme.typography.caption, //use the caption text style
        modifier = Modifier.fillMaxWidth()
    )
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


nba*_*man 6

好吧,在我提到的问题得到解决之前,选择是:

  1. 回滚到 Compose 版本1.0.0-alpha04(问题已在 中引入alpha05
  2. 添加边框到 aTextField或,OutlinedTextField如下所示:
    TextField(
        value = myValue,
        onValueChange = myOnChange,
        modifier = Modifier.clip(myShape).border(5.dp, myColor)
    )
    
    Run Code Online (Sandbox Code Playgroud)

  • 在较新的版本中,您已将形状传递给 TextField 本身,因为它会用传入的形状覆盖剪辑参数 (2认同)

Thi*_*uza 6

通过这个例子,你可以学到很多东西。使用 1.0.0 你可以这样做:

自定义 TextField 打印屏幕在这里

Column {
        var textState by remember { mutableStateOf("") }
        val maxLength = 110
        val lightBlue = Color(0xffd8e6ff)
        val blue = Color(0xff76a9ff)
        Text(
            text = "Caption",
            modifier = Modifier
                .fillMaxWidth()
                .padding(bottom = 4.dp),
            textAlign = TextAlign.Start,
            color = blue
        )
        TextField(
            modifier = Modifier.fillMaxWidth(),
            value = textState,
            colors = TextFieldDefaults.textFieldColors(
                backgroundColor = lightBlue,
                cursorColor = Color.Black,
                disabledLabelColor = lightBlue,
                focusedIndicatorColor = Color.Transparent,
                unfocusedIndicatorColor = Color.Transparent
            ),
            onValueChange = {
                if (it.length <= maxLength) textState = it
            },
            shape = RoundedCornerShape(8.dp),
            singleLine = true,
            trailingIcon = {
                if (textState.isNotEmpty()) {
                    IconButton(onClick = { textState = "" }) {
                        Icon(
                            imageVector = Icons.Outlined.Close,
                            contentDescription = null
                        )
                    }
                }
            }
        )
        Text(
            text = "${textState.length} / $maxLength",
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 4.dp),
            textAlign = TextAlign.End,
            color = blue
        )
    }
Run Code Online (Sandbox Code Playgroud)