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

Flutter TextFormField价格输入格式化需求:自动补两位小数并限制输入长度

Flutter TextFormField价格输入格式化需求:自动补两位小数并限制输入长度

我明白你现在的需求啦——要做一个价格输入框,输入数字时自动补两位小数(比如输入1显示1.00,输入123显示12.30),还得限制最长是5个字符(比如12.30这种格式)。先看看你现有代码里的几个小问题,再给你调整后的完整方案:

现有代码的几个问题

  • onChanged赋值错误:fuelPrice = (fuelPriceValue as TextEditingController);这里完全不对,fuelPriceValue是输入的字符串,不能直接转成TextEditingController类型,应该直接操作controller的文本或者按需处理字符串。
  • 长度限制不匹配:你要的最终格式是XX.XX(5个字符),但现有代码里用了LengthLimitingTextInputFormatter(4),会导致格式化后的文本被截断。
  • 缺少自动补零逻辑:输入1-2位数字时,没有自动补全末尾的.00,不符合价格字段的需求。

修正后的完整代码

// 记得提前初始化controller
final TextEditingController fuelPrice = TextEditingController();

// 价格输入框
TextFormField(
  validator: (fuelPriceValue) {
    if (fuelPriceValue!.isEmpty) {
      return null;
    }
    // 可以加额外的校验,比如价格不能为0
    if (double.tryParse(fuelPriceValue) == 0) {
      return "价格不能为0";
    }
    return null;
  },
  onChanged: (value) {
    // 如果需要把格式化后的价格转成数字做后续处理
    final double? price = double.tryParse(value);
    if (price != null) {
      // 这里写你的业务逻辑,比如更新状态变量
    }
  },
  controller: fuelPrice,
  keyboardType: TextInputType.number,
  inputFormatters: [
    // 限制最终显示的文本长度为5(比如XX.XX)
    LengthLimitingTextInputFormatter(5),
    // 只允许输入数字
    FilteringTextInputFormatter.allow(RegExp(r'\d*')),
    // 自定义格式化逻辑
    TextInputFormatter.withFunction((oldValue, newValue) {
      // 过滤掉所有非数字字符,只保留纯数字
      final digitsOnly = newValue.text.replaceAll(RegExp(r'[^0-9]'), '');
      String formattedText;

      switch (digitsOnly.length) {
        case 0:
          formattedText = '';
          break;
        case 1:
          // 输入1位数字 → X.00
          formattedText = '${digitsOnly[0]}.00';
          break;
        case 2:
          // 输入2位数字 → XX.00
          formattedText = '$digitsOnly.00';
          break;
        case 3:
          // 输入3位数字 → X.XX
          formattedText = '${digitsOnly.substring(0,1)}.${digitsOnly.substring(1)}';
          break;
        case 4:
          // 输入4位数字 → XX.XX
          formattedText = '${digitsOnly.substring(0,2)}.${digitsOnly.substring(2)}';
          break;
        default:
          // 超过4位数字,只取前4位处理
          final trimmedDigits = digitsOnly.substring(0,4);
          formattedText = '${trimmedDigits.substring(0,2)}.${trimmedDigits.substring(2)}';
          break;
      }

      // 确保光标始终在文本末尾,避免格式化后光标跳错位置
      final cursorPosition = formattedText.length;

      return TextEditingValue(
        text: formattedText,
        selection: TextSelection.collapsed(offset: cursorPosition),
      );
    }),
  ],
  decoration: const InputDecoration(
    errorBorder: OutlineInputBorder(),
    border: OutlineInputBorder(),
    contentPadding: EdgeInsets.only(left: 10),
    hintText: "输入价格", // 可以加个提示文本
  ),
);

代码逻辑说明

  1. 输入过滤:先用FilteringTextInputFormatter确保只能输入数字,再在自定义formatter里二次过滤,避免意外字符干扰。
  2. 格式化规则:根据输入的数字位数自动转换为带两位小数的格式,完全符合你要的价格显示需求。
  3. 光标处理:格式化后强制光标在文本末尾,避免用户输入时光标乱跑的问题。
  4. 长度限制:用LengthLimitingTextInputFormatter(5)限制最终显示的文本长度,刚好匹配XX.XX的格式。

备注:内容来源于stack exchange,提问作者Quentinio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 15:42:39