You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:33:12