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

Flutter TextField两位小数输入限制异常:超位输入无显示但可退格删除求助

解决Flutter TextField两位小数输入后无效字符残留问题

问题根源

  1. 原正则表达式r'^\d+\.?\,?\d{0,2}'逻辑错误:允许同时出现小数点和逗号,且未限制小数分隔符的数量,输入校验不严谨。
  2. 使用FilteringTextInputFormatter.allow仅过滤不匹配字符,但无效输入会留在输入缓冲区,退格时需先删除这些不可见的无效内容。
  3. onChanged仅更新变量未同步控制器文本,导致显示内容与实际输入缓冲区不一致。

解决方案

替换原输入格式化器为自定义的TextInputFormatter,严格控制输入格式,同时修正onChanged和onSubmitted的逻辑:

1. 定义自定义输入格式化器

class TwoDecimalInputFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
    // 允许空输入
    if (newValue.text.isEmpty) return newValue;

    // 匹配规则:可选负号 + 整数部分 + 可选小数点 + 0-2位小数
    final regex = RegExp(r'^-?\d*\.?\d{0,2}$');
    if (!regex.hasMatch(newValue.text)) {
      // 不匹配则返回旧值,拒绝无效输入
      return oldValue;
    }

    // 处理单独输入小数点的情况,自动补0
    if (newValue.text == '.') {
      return TextEditingValue(
        text: '0.',
        selection: TextSelection.collapsed(offset: 2),
      );
    }

    // 处理负号后直接输入小数点的情况
    if (newValue.text.startsWith('-.') && newValue.text.length == 2) {
      return TextEditingValue(
        text: '-0.',
        selection: TextSelection.collapsed(offset: 3),
      );
    }

    return newValue;
  }
}

2. 修改TextField代码

TextField(
  controller: extraAmountController,
  inputFormatters: [TwoDecimalInputFormatter()], // 使用自定义格式化器
  keyboardType: TextInputType.numberWithOptions(decimal: true, signed: true),
  onChanged: (amount) {
    if (amount.isEmpty) {
      extraAmount = "0.00";
    } else if (amount.endsWith('.')) {
      // 处理末尾是小数点的情况,转为两位小数格式
      extraAmount = double.parse(amount.replaceAll('.', '')).toStringAsFixed(2);
    } else {
      extraAmount = double.parse(amount).toStringAsFixed(2);
    }
    print(extraAmount);
  },
  onSubmitted: (amount) {
    if (amount.isEmpty) {
      extraAmountController.text = extraAmount = "0.00";
    } else if (amount.endsWith('.')) {
      extraAmount = double.parse(amount.replaceAll('.', '')).toStringAsFixed(2);
      extraAmountController.text = extraAmount;
    } else {
      extraAmount = double.parse(amount).toStringAsFixed(2);
      extraAmountController.text = extraAmount;
    }
    print(extraAmount);
  },
  textAlignVertical: TextAlignVertical.center,
  cursorColor: Colors.black45,
  decoration: InputDecoration(
    hintText: usersList.first.extraAmount,
    contentPadding: const EdgeInsets.only(left: 10),
    suffixIcon: Icon(Icons.business_center, color: Colors.grey),
    border: OutlineInputBorder(
      borderRadius: BorderRadius.circular(5),
      borderSide: BorderSide(color: Colors.grey),
    ),
    enabledBorder: OutlineInputBorder(
      borderRadius: BorderRadius.circular(5),
      borderSide: BorderSide(color: Colors.grey),
    ),
    focusedErrorBorder: OutlineInputBorder(
      borderRadius: BorderRadius.circular(5),
      borderSide: BorderSide(color: Colors.grey),
    ),
    disabledBorder: OutlineInputBorder(
      borderRadius: BorderRadius.circular(5),
      borderSide: BorderSide(color: Colors.grey),
    ),
    errorBorder: OutlineInputBorder(
      borderRadius: BorderRadius.circular(5),
      borderSide: BorderSide(color: Colors.grey),
    ),
    focusedBorder: OutlineInputBorder(
      borderRadius: BorderRadius.circular(5),
      borderSide: BorderSide(color: Colors.grey),
    ),
  ),
)

说明

自定义格式化器会直接拒绝不符合规则的输入,不会让无效内容进入输入缓冲区,彻底解决退格时需删除不可见内容的问题。同时优化了空输入、末尾小数点等边界情况的处理,保证输入格式始终符合两位小数的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 04:45:14