Flutter TextField输入格式化问题:正则表达式导致无法输入合规数值
解决Flutter TextFormField的数字输入限制问题
我来帮你搞定这个输入限制的问题!你当前遇到的无法输入任何内容的原因,是因为你用的正则表达式要求输入必须是完整的、带小数点的多数字序列(用逗号分隔),但用户输入是逐步进行的——比如输入第一个字符"1"时,完全不符合这个正则的完整匹配规则,直接被FilteringTextInputFormatter过滤掉了。
问题分析
你的需求是允许:
- 整数(如
12345) - 小数(如
21321.12312) - 负数(如
-23423.32432)
同时禁止: - 多小数点(如
12..32) - 负号不在开头(如
324-4323)
而原正则r'^(-?\d+\.\d+)(\s*,\s*-?\d+\.\d+)+$'的问题在于:
- 强制要求必须有小数点(
\d+\.\d+),连整数都输不了 - 强制要求至少一个完整的带小数的数字,后面还要跟逗号分隔的其他数字,完全不符合逐步输入的场景
正确的解决方案
我们需要一个能匹配逐步输入过程中所有合法状态的正则表达式,允许空输入、负号开头、整数、小数,同时限制多小数点和负号位置。
单个数字的情况(不允许逗号分隔多个)
使用正则r'^-?\d*\.?\d*$',它的含义是:
^:字符串开头-?:可选的负号(只能在开头)\d*:0个或多个数字(整数部分)\.?:可选的小数点(最多一个)\d*:0个或多个数字(小数部分)$:字符串结尾
修改后的代码:
TextFormField( inputFormatters: [ FilteringTextInputFormatter.allow( RegExp(r'^-?\d*\.?\d*$'), ), ], controller: budget, keyboardType: TextInputType.numberWithOptions(decimal: true, signed: true), decoration: InputDecoration( contentPadding: EdgeInsets.only(right: 20, left: 20, top: 10, bottom: 10), hintText: getTranslated(context, "budget_example"), hintStyle: TextStyle(fontSize: 13, fontFamily: "tahoma"), border: OutlineInputBorder( borderSide: BorderSide(width: 1, color: MyColors.secondary), borderRadius: BorderRadius.circular(100), ), ), )
注意:把keyboardType改成TextInputType.numberWithOptions(decimal: true, signed: true),这样键盘会显示小数点和负号,更符合需求。
允许逗号分隔多个数字的情况
如果你的需求是允许输入多个用逗号分隔的合法数字(比如123, -45.67, 89.0),可以用这个正则r'^-?\d*\.?\d*(?:\s*,\s*-?\d*\.?\d*)*$',它在单个数字的基础上,允许添加逗号和空格分隔的其他合法数字。
对应的inputFormatters:
FilteringTextInputFormatter.allow( RegExp(r'^-?\d*\.?\d*(?:\s*,\s*-?\d*\.?\d*)*$'), ),
额外验证(可选)
如果需要确保最终输入是有效的数字(比如不能只输入负号或小数点),可以在validator回调里做进一步验证:
validator: (value) { if (value == null || value.isEmpty) { return '请输入金额'; } // 验证是否是合法数字 if (!RegExp(r'^-?\d+(\.\d+)?$').hasMatch(value)) { return '请输入合法的数字(整数、小数、负数)'; } return null; },
内容的提问来源于stack exchange,提问作者Mr. ZeroOne
相关产品推荐
相关产品推荐

