Flutter中TextFormField首5字符模糊显示及原文本保留问题求助
解决方案
核心思路
别直接用replaceRange()修改覆盖原始文本,核心是把原始明文和前端显示的模糊文本分开维护:
- 用
_originalText变量全程保存用户输入的真实内容 - 动态生成模糊后的
displayText作为输入框的显示内容 - 通过
TextEditingController监听所有输入操作,根据用户的输入动作(新增、删除、修改)更新原始文本,再同步生成最新的模糊显示文本
完整代码实现
import 'package:flutter/material.dart'; import 'dart:math'; class ObscureTextInput extends StatefulWidget { const ObscureTextInput({super.key}); @override State<ObscureTextInput> createState() => _ObscureTextInputState(); } class _ObscureTextInputState extends State<ObscureTextInput> { late TextEditingController _inputController; String _originalText = ''; // 存储真实输入的明文 @override void initState() { super.initState(); _inputController = TextEditingController(); _inputController.addListener(_updateTextContent); } @override void dispose() { _inputController.dispose(); super.dispose(); } // 处理输入变化,同步更新原始文本和显示文本 void _updateTextContent() { final currentDisplay = _inputController.text; final originalLen = _originalText.length; final displayLen = currentDisplay.length; if (displayLen > originalLen) { // 用户新增字符:把新增部分追加到原始文本 final addedStr = currentDisplay.substring(originalLen); _originalText += addedStr; } else if (displayLen < originalLen) { // 用户删除字符:截断原始文本到对应长度 _originalText = _originalText.substring(0, displayLen); } else { // 用户修改中间字符:找到修改位置,更新原始文本对应内容 final diffIndex = _getFirstDiffIndex(currentDisplay, _makeDisplayText(_originalText)); if (diffIndex != -1) { _originalText = _originalText.replaceRange( diffIndex, diffIndex + 1, currentDisplay[diffIndex], ); } } // 生成最新模糊文本并同步到输入框 final newDisplay = _makeDisplayText(_originalText); if (_inputController.text != newDisplay) { // 避免循环触发监听,用copyWith更新控制器状态 _inputController.value = _inputController.value.copyWith( text: newDisplay, selection: TextSelection.collapsed(offset: _inputController.selection.end), ); } // 这里可以添加原始文本的业务逻辑,比如提交、存储等 print('当前原始明文:$_originalText'); } // 生成模糊显示文本:前5位替换为X,其余保留 String _makeDisplayText(String original) { if (original.length <= 5) { return 'X' * original.length; } else { return 'XXXXX${original.substring(5)}'; } } // 找到两个字符串第一个不同的位置 int _getFirstDiffIndex(String a, String b) { final minLen = min(a.length, b.length); for (int i = 0; i < minLen; i++) { if (a[i] != b[i]) return i; } return a.length == b.length ? -1 : minLen; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('模糊文本输入示例')), body: Padding( padding: const EdgeInsets.all(16.0), child: TextFormField( controller: _inputController, decoration: const InputDecoration( hintText: '请输入内容', border: OutlineInputBorder(), ), ), ), ); } }
关键说明
- 状态完全分离:
_originalText独立于显示文本,任何输入操作都不会覆盖或丢失真实内容 - 精准监听输入:通过控制器的
listener捕捉所有输入动作,针对性更新原始文本 - 避免循环触发:更新显示文本时先判断是否需要修改,用
value.copyWith避免无限触发监听 - 兼容多场景:支持字符新增、删除、中间修改等常见操作,全程保留原始明文的完整性
内容的提问来源于stack exchange,提问作者Prajwal Shinde
相关产品推荐
相关产品推荐

