You need to enable JavaScript to run this app. Flutter 如何实现金额输入框支持输入并格式化带美分的小数金额
优惠活动
大模型
产品
解决方案
定价
更多

Flutter 如何实现金额输入框支持输入并格式化带美分的小数金额

问题根因定位

现有代码无法支持带美分的金额输入,核心是三个配置逻辑的错位:

  • 输入拦截规则过严:inputFormatters 中配置的 WhitelistingTextInputFormatter.digitsOnly 会直接拦截小数点字符,从输入层就阻断了小数录入通道
  • 格式化规则缺失小数占位:自定义类和初始化用到的 NumberFormat 模板都是纯整数格式(#,##0/###,###,###),哪怕能录入小数,格式化时也会把小数部分全部舍去
  • 格式化逻辑没有边界校验:现有自定义格式化类直接把输入文本整体转成double做格式化,没有处理小数点数量、小数位长度的限制,容易出现格式错乱、解析报错的问题
    注:WhitelistingTextInputFormatter 目前已被Flutter官方标记为废弃,推荐替换为 FilteringTextInputFormatter
分步修正实现

1. 调整输入过滤规则

替换原有的纯数字拦截器,改为允许数字和单个小数点输入的过滤规则,从输入层放开小数录入权限:

// 仅允许数字和小数点,替换原有的digitsOnly规则
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),

2. 修正金额格式化模板

把原来的整数格式模板改成固定保留两位小数的美元格式,确保所有金额展示都带美分位:

// 规范的两位小数美元格式,注意locale为规范写法en_US而非小写en_us
final money = NumberFormat('#,##0.00', 'en_US');

3. 重写自定义CurrencyFormat类

补全边界处理逻辑,解决小数点重复输入、小数位过长、解析报错的问题,修正后的完整类实现如下:

class CurrencyFormat extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    // 空输入直接返回
    if (newValue.text.isEmpty) {
      return newValue;
    }

    // 限制小数点只能出现1个,多余的直接截断
    final dotIndex = newValue.text.indexOf('.');
    String processedText = newValue.text;
    if (dotIndex != -1) {
      // 截取第一个小数点前的内容 + 小数点 + 剔除后续重复的小数点
      processedText = newValue.text.substring(0, dotIndex + 1) +
          newValue.text.substring(dotIndex + 1).replaceAll('.', '');
      // 限制小数位最多2位
      final decimalPart = processedText.split('.')[1];
      if (decimalPart.length > 2) {
        processedText = processedText.substring(0, processedText.length - (decimalPart.length - 2));
      }
    }

    // 异常值兜底,避免非数值输入导致崩溃
    double value = 0;
    try {
      value = double.parse(processedText);
    } catch (e) {
      return oldValue;
    }

    // 用带两位小数的格式做千分位格式化
    final money = NumberFormat('#,##0.00', 'en_US');
    String newText = money.format(value);

    // 保持光标在文本末尾,符合输入交互习惯
    return newValue.copyWith(
      text: newText,
      selection: TextSelection.collapsed(offset: newText.length),
    );
  }
}

4. 调整金额输入框的配置

替换原有的inputFormatters列表,同时配置支持小数点的数字键盘,确保拦截规则和自定义格式化逻辑配合生效:

TextFormField(
  keyboardType: const TextInputType.numberWithOptions(decimal: true), // 唤起带小数点的数字键盘
  inputFormatters: [
    // 替换原有的digitsOnly规则
    FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
    CurrencyFormat()
  ],
  onSaved: (e) => payment = e,
  decoration: InputDecoration(
      labelText: 'AMOUNT',
      enabledBorder: OutlineInputBorder(
          borderSide: BorderSide(
        color: Color(0xff083663),
      )),
      border: OutlineInputBorder()),
)
可选优化:通用支付场景输入体验

如果需要适配主流支付产品的输入逻辑(用户无需手动输入小数点,系统自动将输入的最后两位识别为美分,比如输入79424自动展示为794.24,输入123自动展示为1.23),可以把CurrencyFormat里的数值计算逻辑做调整:把输入的纯数字字符串转成整数后除以100,再走同样的格式化流程即可。


内容的提问来源于stack exchange,提问作者flutter run

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.11 18:06:03