如何解决Flutter TextField日期场景下的数字输入校验问题
问题原因总述
你遇到的两个问题根源都是正则表达式使用错误:方括号[]在正则中是单个字符匹配规则,你写的[1-31]、[1-12]、[1952-2003]写法完全不符合正则语法,只会匹配括号内出现过的单个字符,无法实现范围校验。
1. 日月仅支持带前导零的两位格式解决方案
核心修改点
- 替换错误的范围正则为正确的两位带前导零匹配规则
- 增加输入过程校验,禁止第一位输入非0的字符
修改后的月份输入配置
TextFormField( textInputAction: TextInputAction.next, keyboardType: TextInputType.number, maxLength: 2, controller: myControllerMonth, inputFormatters: <TextInputFormatter>[ // 兼容输入过程的正则,仅允许输入0开头、后续符合01-12规则的内容 FilteringTextInputFormatter.allow(RegExp(r'^0?[1-9]?|1[0-2]?$')), ], onChanged: (valueMonth) { // 第一位输入非0直接清空,强制带前导零 if(valueMonth.length == 1 && valueMonth != '0') { myControllerMonth.clear(); // 可自行添加Toast提示用户输入规则 return; } if (valueMonth.length == 2) { FocusScope.of(context).nextFocus(); } valueMonthKey = valueMonth; } )
修改后的日期输入配置
TextFormField( textInputAction: TextInputAction.next, keyboardType: TextInputType.number, maxLength: 2, controller: myControllerDay, inputFormatters: <TextInputFormatter>[ // 兼容输入过程的正则,仅允许输入0开头、后续符合01-31规则的内容 FilteringTextInputFormatter.allow(RegExp(r'^0?[1-9]?|[1-2][0-9]?|3[0-1]?$')), ], onChanged: (valueDay) { // 第一位输入非0直接清空,强制带前导零 if(valueDay.length == 1 && valueDay != '0') { myControllerDay.clear(); // 可自行添加Toast提示用户输入规则 return; } if (valueDay.length == 2) { FocusScope.of(context).nextFocus(); } valueDayKey = valueDay; } )
2. 年份无法输入部分数字解决方案
核心修改点
替换错误的年份范围正则为正确的4位数字匹配规则,支持1952-2003全范围数字输入
修改后的年份输入配置
TextFormField( textInputAction: TextInputAction.done, keyboardType: TextInputType.number, maxLength: 4, controller: myControllerYear, inputFormatters: <TextInputFormatter>[ // 兼容输入过程的正则,覆盖1952-2003全范围 FilteringTextInputFormatter.allow(RegExp(r'^1?9?5?[2-9]?|1?9?[6-9]?[0-9]?|2?0?0?[0-3]?$')), ], onChanged: (valueYear) { if (valueYear.length == 4) { FocusScope.of(context).unfocus(); } valueYearKey = valueYear; // 仅当三个输入项都完整时再做日期解析,避免下标越界崩溃 if(valueDayKey?.length == 2 && valueMonthKey?.length == 2 && valueYear.length == 4) { try { DateTime _dateTime = DateTime( int.parse(valueYearKey), int.parse(valueMonthKey), int.parse(valueDayKey), ); // 简化年龄计算逻辑,避免原写法的计算误差 age = DateTime.now().difference(_dateTime).inDays ~/ 365; UserAge.age = age; } catch(e) { // 捕获非法日期异常,比如02月31日这类不存在的日期 print('日期输入不合法:$e'); } } } )
额外优化建议
可以在用户提交表单前再增加一次全局校验,确认日、月、年都是合法的两位/四位格式,避免极端场景下的非法输入。
内容的提问来源于stack exchange,提问作者VegetaSaiyan
相关产品推荐
相关产品推荐

