Flutter FilteringTextInputFormatter实现数字加至多1个连字符输入校验的问题
问题本质
FilteringTextInputFormatter的工作逻辑和RegexPal上的全串匹配逻辑存在本质差异,这是导致连字符无法输入的核心原因:
FilteringTextInputFormatter.allow的运行规则是从用户输入的内容片段中,筛选所有匹配正则的字符保留,不匹配的字符直接拦截丢弃,不会拿最终的完整输入文本做从头至尾的全匹配校验。- 你修改后的正则
^([0-9]+(\-[0-9]+)?)做了字符串开头锚定,要求匹配内容必须以数字为起始,后续才能跟连字符序列。当用户单独输入一个连字符时,这个单字符既不属于数字,也不满足“数字开头”的前置匹配要求,会被直接判定为非法内容拦截,因此完全无法输入连字符。 - 最初使用的
[0-9-]+正则没有设置连字符的数量限制,因此会允许多个连字符输入;单靠逐字符筛选的正则本身也没法记录用户已经输入过的连字符总数,天然不适合做多字符全局数量限制。
适配需求的落地方案
针对“仅允许输入数字、全串最多出现1个连字符”的要求,不需要把全串校验正则硬套在过滤格式化器上,两种可直接复用的实现方式:
- 基础过滤+监听校验组合
先用FilteringTextInputFormatter.allow(RegExp('[0-9-]'))拦截数字、连字符之外的所有非法内容,再给输入框绑定文本变化监听,每次文本更新时执行两项校验: - 统计当前文本中的连字符总数,如果超过1个,自动删除多余的连字符
- 如果连字符出现在字符串最开头,直接移除该位置的连字符
这种方式对输入体验的干扰最小,不会出现输入字符被莫名拦截的割裂感。 - 自定义全串校验格式化器
不使用内置的过滤型格式化器,自行实现TextInputFormatter接口,每次输入内容变化时,用最终合法规则对应的正则^(?!.*-.*-)[0-9]+-?[0-9]*$匹配完整输入文本,匹配不通过就自动回退到上一个合法的输入状态。这个正则内置了最多1个连字符、无非数字非法字符的校验逻辑,同时兼容输入中途的临时状态(比如刚输完数字、刚输完连字符还没补后续数字的场景),不会出现误拦截合法输入的问题。
内容的提问来源于stack exchange,提问作者Chance
相关产品推荐
相关产品推荐

