Jetpack Compose 密码输入框如何动态切换visualTransformation实现显隐
切换密码明文/密文失效的核心原因
- 组件未维护密码可见性的可观察状态,缺少能触发Compose重组的状态源
- 密码展示图标的点击回调为空,点击操作没有产生任何状态更新
- 静态传入的
visualTransformation参数不会随用户操作动态切换值,无法触发输入框的视觉更新 - 原有代码存在modifier重复应用的小问题:外部传入的修饰符同时作用于外层Box和内部BasicTextField,会造成样式叠加异常
具体实现调整方案
- 在组件内部新增记忆化的密码可见性状态,状态值变更时会自动触发Compose重组
- 给密码展示图标的点击事件绑定状态切换逻辑,点击时反转可见性布尔值
- 根据当前可见性状态、输入框类型动态生成对应的
visualTransformation:密码密文场景用PasswordVisualTransformation(),明文场景用VisualTransformation.None - 可根据可见性状态动态切换眼睛图标的展示资源,优化交互反馈
调整后可正常运行的代码
fun UserInputText( keyboardType: KeyboardType = KeyboardType.Text, onTextChanged: (TextFieldValue) -> Unit, textFieldValue: TextFieldValue, visualTransformation: VisualTransformation = VisualTransformation.None, borderColor: Color = editTextBorderColor, keyboardShown: Boolean, onTextFieldFocused: (Boolean) -> Unit, focusState: Boolean, placeholder: String = "", modifier: Modifier = Modifier ) { // 新增密码可见性的可观察状态 var isPasswordVisible by remember { mutableStateOf(false) } Box( modifier = modifier.border( width = 2.dp, color = borderColor, shape = RoundedCornerShape(16.dp) ) ) { var lastFocusState by remember { mutableStateOf(FocusState.Inactive) } val focusRequester = FocusRequester() val focusRequesterModifier = Modifier.focusRequester(focusRequester) BasicTextField( value = textFieldValue, onValueChange = { onTextChanged(it) }, // 修正原有modifier重复应用的问题,去掉多余的外层modifier引用 modifier = Modifier .focus() .then(focusRequesterModifier) .align(Alignment.TopStart) .padding(16.dp) // 给输入框加内边距避免文字贴边 .focusObserver { state -> if (lastFocusState != state) { onTextFieldFocused(state == FocusState.Active) } lastFocusState = state }, keyboardOptions = KeyboardOptions( keyboardType = keyboardType, imeAction = ImeAction.Send ), // 动态根据输入类型和可见性状态生成视觉变换 visualTransformation = if (keyboardType == KeyboardType.Password) { if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation() } else visualTransformation, maxLines = 1, cursorColor = inputTextColor, textStyle = MaterialTheme.typography.body1.copy(color = inputTextColor) ) if(keyboardType == KeyboardType.Password) { Image( // 可根据状态动态切换图标资源 vectorResource( id = if (isPasswordVisible) R.drawable.ic_eye_open else R.drawable.ic_eye_closed ), modifier = Modifier .align(Alignment.TopEnd) .padding(end = 16.dp, top = 16.dp) .clickable { // 绑定点击事件切换可见性 isPasswordVisible = !isPasswordVisible } ) } } }
内容的提问来源于stack exchange,提问作者clouddy
相关产品推荐
相关产品推荐

