如何在 Jetpack Compose 的 OutlinedTextField 中显示错误消息

Cam*_*ila 38 android kotlin android-jetpack-compose android-compose-textfield

我需要显示错误消息OutlinedTextField,但没有找到任何有关如何执行此操作的文档。我在教程中找到了几种方法,例如使用提示创建自定义输入字段或Text在输入字段下方创建,但它们很旧,也许有更好的方法。我需要显示这样的错误消息:

在此输入图像描述

代码:

@Composable
fun EmailInputField(value: MutableState<String>, state: AuthState) {

    OutlinedTextField(
        value = value.value,
        onValueChange = { value.value = it },
        modifier = Modifier.fillMaxWidth(1f).height(60.dp),
        textStyle = TextStyle(color = Color.White),
        label = { Text(text = "Email", color = Color.White) },
        colors = TextFieldDefaults.outlinedTextFieldColors(
            focusedBorderColor = blue,
            unfocusedBorderColor = Color.White
        ),
        isError = state is AuthState.ValidationError,
        singleLine = true
    )
}
Run Code Online (Sandbox Code Playgroud)

Gab*_*tti 69

使用M3,您可以使用属性supportingText,该属性是显示在文本字段下方的可选支持文本。

    val errorMessage = "Text input too long"
    var text by rememberSaveable { mutableStateOf("") }
    var isError by rememberSaveable { mutableStateOf(false) }
    val charLimit = 10

    fun validate(text: String) {
        isError = text.length > charLimit
    }

    TextField(
        value = text,
        onValueChange = {
            text = it
            validate(text)
        },
        singleLine = true,
        isError = isError,
        supportingText = {
            if (isError) {
                Text(
                    modifier = Modifier.fillMaxWidth(),
                    text = "Limit: ${text.length}/$charLimit",
                    color = MaterialTheme.colorScheme.error
                )
            }
        },
        trailingIcon = {
            if (isError)
                Icon(Icons.Filled.Error,"error", tint = MaterialTheme.colorScheme.error)
        },
        keyboardActions = KeyboardActions { validate(text) },
    )
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


M2 组件TextField不支持errorMessage字段。

您可以使用以下方法轻松实现它:

var text by rememberSaveable { mutableStateOf("") }
var isError by rememberSaveable { mutableStateOf(false) }

fun validate(text: String) {
    isError = /* .... */
}

Column {
    TextField(
        value = text,
        onValueChange = {
            text = it
            isError = false
        },
        trailingIcon = {
            if (isError)
            Icon(Icons.Filled.Error,"error", tint = MaterialTheme.colors.error)
        },
        singleLine = true,
        isError = isError,
        keyboardActions = KeyboardActions { validate(text) },
    )
    if (isError) {
        Text(
            text = "Error message",
            color = MaterialTheme.colors.error,
            style = MaterialTheme.typography.caption,
            modifier = Modifier.padding(start = 16.dp)
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 这里的问题是关于“BringIntoViewRequester”。TextField 管理自己的“BringIntoViewRequester”,当该位置被键盘覆盖时,它会自行抬起以防止被覆盖。除非我们管理错误文本焦点请求者,否则当调用 TextField 的 `BringIntoViewRequester` 时,用户将看不到它。 (3认同)

Abh*_*bhi 12

更新

在 Jetpack Compose Material 3 版本1.0.0(2022 年 10 月 24 日发布)中,我们可以使用OutlinedTextFieldsupportingText中的属性

图片来自文档 截图

supportingText需要一个可组合项。


参考
撰写材料 3 发行说明

  • 我很困惑。我看到了屏幕截图,我阅读了文档,但“OutlinedTextField”没有参数“支持文本”我缺少什么? (4认同)

que*_*gre 10

这是一个随时可用的可组合项,您可以将其复制粘贴到代码中。它有一个String名为的字段error,只要该字段不为空,就会显示错误(这样您就只有一个状态变量需要跟踪)。它有点冗长,因此您可以像任何人一样自定义它OutlinedTextField

在此输入图像描述

示例用法

OutlinedTextFieldValidation(
        value = studentState.firstName.value,
        onValueChange = { onFirstNameChange(it) },
        label = { Text(text = "First name") },
        error = "field cannot be empty"
    )
Run Code Online (Sandbox Code Playgroud)

要复制的代码:

@Composable
fun OutlinedTextFieldValidation(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier.fillMaxWidth(0.8f),
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: @Composable (() -> Unit)? = null,
    placeholder: @Composable (() -> Unit)? = null,
    leadingIcon: @Composable (() -> Unit)? = null,
    error: String = "",
    isError: Boolean = error.isNotEmpty(),
    trailingIcon: @Composable (() -> Unit)? = {
        if (error.isNotEmpty())
            Icon(Icons.Filled.Error, "error", tint = MaterialTheme.colors.error)
    },
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    singleLine: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    shape: Shape = MaterialTheme.shapes.small,
    colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors(
        disabledTextColor = Color.Black
    )

) {

    Column(modifier = modifier
        .padding(8.dp)) {
        OutlinedTextField(
            enabled = enabled,
            readOnly = readOnly,
            value = value,
            onValueChange = onValueChange,
            modifier = Modifier
                .fillMaxWidth(),
            singleLine = singleLine,
            textStyle = textStyle,
            label = label,
            placeholder = placeholder,
            leadingIcon = leadingIcon,
            trailingIcon = trailingIcon,
            isError = isError,
            visualTransformation = visualTransformation,
            keyboardOptions = keyboardOptions,
            keyboardActions = keyboardActions,
            maxLines = maxLines,
            interactionSource = interactionSource,
            shape = shape,
            colors = colors
        )
        if (error.isNotEmpty()) {
            Text(
                text = error,
                color = MaterialTheme.colors.error,
                style = MaterialTheme.typography.caption,
                modifier = Modifier.padding(start = 16.dp, top = 0.dp)
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)