Flutter如何通过监听器实现TextFormField限长与卡号格式化
Flutter 自定义键盘场景下银行卡号输入监听器实现
核心规则
- 银行卡号纯数字位最长16位
- 输入过程中每4位自动添加空格分隔,展示格式为
XXXX XXXX XXXX XXXX - 所有逻辑通过
TextEditingController监听器实现,不依赖输入框自带的maxLength、inputFormatters属性 - 适配自定义数字键盘输入场景,避免光标错位、监听死循环问题
前置准备
已完成的开发项无需调整:
- 控制器监听器方法注册
CardNumberFormatter自定义格式化类CommonTextFormField通用输入框封装- 自定义数字键盘唤起逻辑
监听器补全逻辑
首先在对应页面的状态类中添加递归拦截标记位,避免修改控制器文本时反复触发监听导致死循环:
// 格式化执行标记,防止递归触发 bool _isCardFormatProcessing = false;
在已经注册的监听方法中补充以下逻辑:
void _onCardNumberInput() { // 格式化执行中直接拦截,避免死循环 if (_isCardFormatProcessing) return; // 1. 提取纯数字:过滤所有空格、非数字异常字符 final String currentInput = cardNumberController.text; final String pureNumber = currentInput.replaceAll(RegExp(r'\D'), ''); // 2. 超长截断:最多保留16位有效数字 final String validNumber = pureNumber.length > 16 ? pureNumber.substring(0, 16) : pureNumber; // 3. 调用已实现的CardNumberFormatter做4位空格分隔 final TextEditingValue formattedResult = CardNumberFormatter().formatEditUpdate( TextEditingValue(text: currentInput), TextEditingValue(text: validNumber), ); // 4. 格式化后内容无变化则跳过更新 if (formattedResult.text == currentInput) return; // 5. 安全更新控制器内容,光标固定到输入末尾避免错位 _isCardFormatProcessing = true; cardNumberController.value = formattedResult.copyWith( selection: TextSelection.collapsed(offset: formattedResult.text.length), ); _isCardFormatProcessing = false; }
适配说明
- 输入、删除操作都能自动适配空格分隔规则,删除到分隔位时会自动处理多余空格
- 自定义键盘输入任何非数字内容都会被自动过滤,不会污染卡号内容
- 提交卡号时移除所有空格即可得到16位纯数字串:
// 提交接口用的纯卡号 final String submitCardNumber = cardNumberController.text.replaceAll(' ', '');
内容的提问来源于stack exchange,提问作者kartheeki j
相关产品推荐
相关产品推荐

