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("取消") } }) }
关键修改点
密码输入框的
onValueChange逻辑:- 明确允许空字符串通过(
it.isEmpty() || it.length <=8),确保对话框取消时的清空操作能正常同步状态 - 调整错误状态判断为
it.isNotEmpty() && it.length <8,避免空字符串时显示错误提示
- 明确允许空字符串通过(
邮箱输入框的错误判断优化:
- 增加
reauthEmail.isNotEmpty()的判断,避免空邮箱时显示格式错误提示
- 增加
这样修改后,既解决了对话框取消时密码未清空的问题,又严格限制了密码输入长度不超过8位,同时在输入过程中给出正确的错误提示,确认按钮也仅在密码为8位且邮箱格式正确时才启用。
内容的提问来源于stack exchange,提问作者Shivam
相关产品推荐
相关产品推荐

