Flutter中如何通过正则限制输入框仅允许输入小数与带分数
Flutter输入框限制输入合法十进制小数/带分数实现方案
实现分两个核心环节:一是输入过程的实时字符拦截,避免用户输入非法字符,同时保留输入过程的合法中间态(比如输入到一半的小数点、斜杠,避免卡输入);二是输入完成后的严格格式校验,拦截不完整的无效内容。
核心正则规则说明
1. 输入拦截用正则(宽松匹配,适配输入过程)
用于输入框的输入格式化器,允许的合法中间态包括:
- 空内容、纯数字串
- 带小数点的小数输入态(比如
123.、.45这类输入过程中的临时值) - 带分数输入态(比如
2、2 3、2 3/这类临时值)
对应正则pattern:
^(\d*\.?\d*|\d+ \d*\/?\d*)$
2. 最终校验用正则(严格匹配,仅允许合法终值)
用于提交输入、输入框失焦时的合法性判断,仅认可完整合法值:
- 合法十进制小数:不允许前导零(比如
012非法)、不允许末尾悬空小数点、小数部分存在时必须有数字 - 合法带分数:格式为
整数 分子/分母,整数、分子、分母都为正整数,且分数部分必须是真分数(分子<分母)
具体代码实现
首先导入依赖:
import 'package:flutter/services.dart'; import 'dart:core';
给输入框配置输入格式化器,做实时拦截:
TextField( // 带分数需要输入空格、斜杠,不能用纯数字键盘,不需要带分数可切换为数字小数键盘 keyboardType: TextInputType.text, inputFormatters: [ FilteringTextInputFormatter.allow( RegExp(r'^(\d*\.?\d*|\d+ \d*\/?\d*)$'), ), ], // 可在onChanged、onEditingComplete、提交逻辑里调用校验方法 onChanged: (value) { final isValid = isValidNumber(value); // 这里可根据校验结果做错误提示 }, // 其他输入框属性按需配置 )
编写严格校验方法:
/// 校验输入内容是否为合法十进制小数/带分数 bool isValidNumber(String input) { if (input.trim().isEmpty) return false; // 合法小数匹配规则 final decimalReg = RegExp(r'^(0|[1-9]\d*)(\.\d+)?$'); if (decimalReg.hasMatch(input)) return true; // 带分数基础格式匹配 final mixedFractionReg = RegExp(r'^([1-9]\d*) ([1-9]\d*)/([1-9]\d*)$'); final matched = mixedFractionReg.firstMatch(input); if (matched != null) { // 额外判断分数部分为真分数,不需要该限制可直接返回true final numerator = int.parse(matched.group(2)!); final denominator = int.parse(matched.group(3)!); return numerator < denominator; } return false; }
自定义调整规则
- 不需要带分数支持:删除正则中
|\d+ \d*\/?\d*的部分即可,键盘可切换为TextInputType.numberWithOptions(decimal: true) - 需要支持负数:在两个正则的最开头添加
-?即可,比如^-?(0|[1-9]\d*)(\.\d+)?$ - 需要限制小数位数:将小数匹配规则中的
\d+改为对应位数限制,比如最多2位小数就写为\d{0,2} - 允许
.123这类省略整数位0的小数写法:将小数匹配正则改为^(\d+\.?\d+|\.\d+)$
内容的提问来源于stack exchange,提问作者David Davis
相关产品推荐
相关产品推荐

