Flutter中TextFormField密码字段完全隐藏:设置obscureText=true仍显示输入字符
Flutter彻底隐藏TextFormField密码输入(无短暂显示)
默认设置obscureText: true时,Flutter的TextFormField会短暂显示刚输入的字符,要实现完全隐藏所有输入字符的效果,可以用以下两种方案:
方案1:自定义TextEditingController(推荐)
这个方案把显示的掩码文本和真实密码分离,输入过程中始终只显示掩码,不会暴露任何输入内容:
class ObscuredTextController extends TextEditingController { final String obscureChar; String _realPassword = ''; ObscuredTextController({this.obscureChar = '•'}); @override TextSpan buildTextSpan({required BuildContext context, TextStyle? style, required bool withComposing}) { // 始终渲染全掩码的文本 return TextSpan(style: style, text: obscureChar * _realPassword.length); } @override set text(String newText) { _realPassword = newText; super.text = obscureChar * newText.length; } @override String get text => _realPassword; @override void updateEditingValue(TextEditingValue newValue) { final textLengthDelta = newValue.text.length - value.text.length; if (textLengthDelta > 0) { // 新增字符:追加到真实密码 _realPassword += newValue.text.substring(value.text.length); } else if (textLengthDelta < 0) { // 删除字符:截断真实密码 _realPassword = _realPassword.substring(0, _realPassword.length + textLengthDelta); } // 更新显示内容为全掩码 super.updateEditingValue(TextEditingValue( text: obscureChar * _realPassword.length, selection: TextSelection.collapsed(offset: _realPassword.length), )); } }
使用示例:
final passwordController = ObscuredTextController(); TextFormField( controller: passwordController, decoration: const InputDecoration(labelText: '密码'), // 提交时直接通过controller.text获取真实密码 onSaved: (value) { final realPassword = passwordController.text; // 处理密码逻辑 }, )
方案2:自定义InputFormatter
如果不想自定义控制器,可以用输入格式化器实时替换输入内容为掩码,同时保留真实密码:
class ObscureInputFormatter extends TextInputFormatter { final String obscureChar; final StringBuffer _realPassword = StringBuffer(); ObscureInputFormatter({this.obscureChar = '•'}); @override TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { final lengthDelta = newValue.text.length - oldValue.text.length; if (lengthDelta > 0) { // 记录新增的真实字符 _realPassword.write(newValue.text.substring(oldValue.text.length)); } else if (lengthDelta < 0) { // 删除字符时截断真实密码 final newRealLength = _realPassword.length + lengthDelta; final tempText = _realPassword.toString().substring(0, newRealLength); _realPassword.clear(); _realPassword.write(tempText); } // 返回掩码后的显示文本 return TextEditingValue( text: obscureChar * _realPassword.length, selection: TextSelection.collapsed(offset: _realPassword.length), ); } // 获取真实密码的方法 String get realPassword => _realPassword.toString(); }
使用示例:
final obscureFormatter = ObscureInputFormatter(); TextFormField( inputFormatters: [obscureFormatter], decoration: const InputDecoration(labelText: '密码'), onFieldSubmitted: (_) { final realPassword = obscureFormatter.realPassword; // 处理密码逻辑 }, )
两种方案都能彻底避免输入字符的短暂显示,方案1的控制器更便于全局管理和获取真实密码,方案2适合局部场景使用。
内容的提问来源于stack exchange,提问作者Suretion
相关产品推荐
相关产品推荐

