Jetpack Compose:自定义文本字段设计

问题描述 投票:0回答:5

总的来说,Jetpack Compose 中的大多数组件似乎都很容易定制。

但是,

TextField
却不能这么说。例如,假设我想做这样的东西:

有人会认为简单地包裹

BaseTextField
就可以了。但是,
BaseTextField
组件中似乎存在错误,我已经提出了问题。此错误将不允许用户在焦点离开文本字段一次后将焦点集中在文本字段上,直到重新渲染组件。

引用此内容,我尝试自定义

OutlinedTextField
TextField
组件,但无法将它们自定义为如上图所示。如果不是因为光标颜色使用了
activeColor
属性,我就能让它工作。

创建如上所示的可用文本字段的正确解决方法是什么?

android android-jetpack-compose android-jetpack android-textinputlayout android-compose-textfield
5个回答
47
投票

您可以使用

TextField

  • label = null
  • 去除标签
  • 使用
    TextFieldDefaults.textFieldColors
    参数应用自定义颜色来隐藏指示器。
  • onValueChange
    中添加一个函数来固定最大字符数,如此处
  • 所述

最后使用

Column
添加 2 个
Text
可组合项来完成外部标签和计数器文本。

类似:

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()
    )


36
投票

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

Custom TextField printscreen here

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
        )
    }

6
投票

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

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

4
投票

除了 Gabriele Mariotti 的回答
如果您喜欢自定义光标颜色,可以使用以下方法实现:

Column(){
    //External label
    Text(
        ...
        ...
    )

    TextField(
        ...
        ...

        colors = TextFieldDefaults.textFieldColors(
            backgroundColor = ...,
            focusedIndicatorColor =  ..., 
            unfocusedIndicatorColor = ...,
            cursorColor = Color.Black)
    )
    //counter message
    Text(
        ...
        ...
    )

0
投票

对于材料3

TextField(
        value = text,
        onValueChange = {
            text = it
        },
        shape = RoundedCornerShape(8.dp),
        colors = TextFieldDefaults.colors().copy(
            focusedContainerColor = md_grey_200,
            focusedTextColor = md_black_1000,
            unfocusedTextColor = md_black_1000,
            focusedIndicatorColor = md_transparent,
            unfocusedContainerColor = md_grey_200,
            unfocusedIndicatorColor = md_transparent
        )
    )

TextFieldDefaults.colors().copy() 有助于保持代码最少,仅更改您想要的颜色

© www.soinside.com 2019 - 2024. All rights reserved.