You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose重认证对话框密码TextField无法清空及验证需求

问题解决:对话框取消时密码未清空,同时限制密码为8位

问题分析

取消重认证对话框时,邮箱能正常清空但密码保留,原因是密码输入框的onValueChange中it.length <=8的条件,虽空字符串符合该条件,但状态更新时序问题导致清空操作未正确生效;移除该条件后清空恢复,但又无法限制密码长度。需同时满足:

  • 对话框取消时密码可正常清空
  • 用户无法输入超过8位的密码,少于8位时显示错误提示

解决方案

修改密码输入框的onValueChange逻辑,明确允许空字符串(用于清空),同时限制输入长度不超过8位;优化错误状态判断逻辑,确保状态更新正确。

修改后的完整代码

var reauthEmail by remember { mutableStateOf("") }
var reauthPassword by remember { mutableStateOf("") }

ReauthDialog(
    onDismiss = {
        showReauthDialog = false
        reauthEmail = ""
        reauthPassword = ""
    },
    onConfirm = {
        reauthErrorMessage = ""
        profileEditViewModel.reauthenticateUser(reauthEmail, reauthPassword, {
            showReauthDialog = false
            onReauthCompleted = true
        }, { errorMessage ->
            reauthErrorMessage = errorMessage
        })
    },
    reauthEmail = reauthEmail,
    onReauthEmailChange = { reauthEmail = it },
    reauthPassword = reauthPassword,
    onReauthPasswordChange = {
        reauthPassword = it
    },
    reauthErrorMessage
)
}

@Composable
fun ReauthDialog(
    onDismiss: () -> Unit,
    onConfirm: () -> Unit,
    reauthEmail: String,
    onReauthEmailChange: (String) -> Unit,
    reauthPassword: String,
    onReauthPasswordChange: (String) -> Unit,
    reauthErrorMessage: String
) {
    var isEmailError by remember { mutableStateOf(false) }
    var isPasswordError by remember { mutableStateOf(false) }

    AlertDialog(
        titleContentColor = Color.White,
        containerColor = Category_Indicator,
        onDismissRequest = {
            onReauthEmailChange("")
            onReauthPasswordChange("")
            isEmailError = false
            isPasswordError = false
            onDismiss()
        },
        title = { Text(text = "重新认证") },
        text = {
            Column {
                TextField(
                    value = reauthEmail,
                    singleLine = true,
                    onValueChange = {
                        onReauthEmailChange(it)
                        isEmailError = reauthEmail.isNotEmpty() && !Patterns.EMAIL_ADDRESS.matcher(reauthEmail).matches()
                    },
                    label = { Text("邮箱") },
                    keyboardOptions = KeyboardOptions(
                        keyboardType = KeyboardType.Email, imeAction = ImeAction.Next
                    ),
                    supportingText = {
                        if (isEmailError) {
                            Text(
                                text = "邮箱格式无效",
                                color = Color.Red,
                                fontSize = 12.ssp,
                            )
                        }
                    },
                    isError = isEmailError,
                    colors = TextFieldDefaults.colors(
                        unfocusedContainerColor = Category_Indicator,
                        focusedContainerColor = Category_Indicator,
                        unfocusedTextColor = Color.White,
                        focusedTextColor = Color.White,
                        errorTextColor = Color.White,
                        cursorColor = Color.White,
                        focusedIndicatorColor = Color.White,
                        errorContainerColor = Category_Indicator,
                        unfocusedIndicatorColor = Color.White,
                        unfocusedLabelColor = Color.White,
                        focusedLabelColor = Color.White,
                    )
                )

                Spacer(modifier = Modifier.height(10.sdp))

                var passwordVisibility: Boolean by remember { mutableStateOf(false) }
                TextField(
                    visualTransformation = if (passwordVisibility) VisualTransformation.None else PasswordVisualTransformation(),
                    trailingIcon = {
                        IconButton(onClick = {
                            passwordVisibility = !passwordVisibility
                        }) {
                            Icon(
                                tint = Color.White,
                                painter = painterResource(id = if (passwordVisibility) R.drawable.ic_show_password else R.drawable.ic_hide_password),
                                contentDescription = null,
                                modifier = Modifier.size(20.sdp)
                            )
                        }
                    },
                    value = reauthPassword,
                    singleLine = true,
                    onValueChange = {
                        // 允许空字符串(用于清空),同时限制输入长度不超过8位
                        if (it.isEmpty() || it.length <= 8) {
                            onReauthPasswordChange(it)
                        }
                        // 错误状态:非空且长度小于8位时提示错误
                        isPasswordError = it.isNotEmpty() && it.length < 8
                    },
                    label = { Text("密码") },
                    keyboardOptions = KeyboardOptions(
                        keyboardType = KeyboardType.Password, imeAction = ImeAction.Done
                    ),
                    supportingText = {
                        if (isPasswordError) {
                            Text(
                                text = "密码必须至少8位",
                                color = Color.Red,
                                fontSize = 12.ssp,
                            )
                        }
                    },
                    isError = isPasswordError,
                    colors = TextFieldDefaults.colors(
                        unfocusedContainerColor = Category_Indicator,
                        focusedContainerColor = Category_Indicator,
                        unfocusedTextColor = Color.White,
                        focusedTextColor = Color.White,
                        errorTextColor = Color.White,
                        cursorColor = Color.White,
                        focusedIndicatorColor = Color.White,
                        errorContainerColor = Category_Indicator,
                        unfocusedIndicatorColor = Color.White,
                        unfocusedLabelColor = Color.White,
                        focusedLabelColor = Color.White,
                    )
                )

                Text(text = reauthErrorMessage, color = Color.Red)
            }
        },
        confirmButton = {
            Button(
                colors = ButtonDefaults.buttonColors(
                    containerColor = Purple_Button,
                    contentColor = Color.White
                ),
                enabled = (reauthEmail.isNotEmpty() && Patterns.EMAIL_ADDRESS.matcher(reauthEmail).matches())
                        && (reauthPassword.isNotEmpty() && reauthPassword.length == 8),
                onClick = onConfirm
            ) {
                Text("确认")
            }
        },
        dismissButton = {
            Button(
                colors = ButtonDefaults.buttonColors(
                    containerColor = Color.White,
                    contentColor = Color.Black
                ),
                onClick = {
                    onDismiss()
                }
            ) {
                Text("取消")
            }
        })
}

关键修改点

  1. 密码输入框的onValueChange逻辑:

    • 明确允许空字符串通过(it.isEmpty() || it.length <=8),确保对话框取消时的清空操作能正常同步状态
    • 调整错误状态判断为it.isNotEmpty() && it.length <8,避免空字符串时显示错误提示
  2. 邮箱输入框的错误判断优化:

    • 增加reauthEmail.isNotEmpty()的判断,避免空邮箱时显示格式错误提示

这样修改后,既解决了对话框取消时密码未清空的问题,又严格限制了密码输入长度不超过8位,同时在输入过程中给出正确的错误提示,确认按钮也仅在密码为8位且邮箱格式正确时才启用。

内容的提问来源于stack exchange,提问作者Shivam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:14:56