Flutter TextFormField输入格式化器求助:特定格式输入限制
实现符合指定格式的TextFormField输入格式化器
针对你需要的「两位字符-四位数字-两位数字-四位/五位数字」格式,我们可以自定义一个TextInputFormatter来实现,下面是完整的实现方案:
1. 自定义输入格式化器类
创建一个CustomCodeFormatter类,继承TextInputFormatter,核心逻辑在formatEditUpdate方法中处理输入内容:
class CustomCodeFormatter extends TextInputFormatter { @override TextEditingValue formatEditUpdate( TextEditingValue oldValue, TextEditingValue newValue, ) { // 移除所有分隔符,处理原始输入内容 final cleanText = newValue.text.replaceAll('-', ''); String formattedText = ''; // 验证并分段处理输入 if (cleanText.isNotEmpty) { // 第一段:两位英文字符 final firstSegment = cleanText.substring(0, cleanText.length > 2 ? 2 : cleanText.length); // 只允许英文字符 final validFirstSegment = firstSegment.replaceAll(RegExp(r'[^A-Za-z]'), ''); formattedText += validFirstSegment; // 如果第一段长度达到2,添加分隔符并处理第二段(四位数字) if (validFirstSegment.length == 2 && cleanText.length > 2) { formattedText += '-'; final secondSegmentStart = 2; final secondSegmentEnd = cleanText.length > 6 ? 6 : cleanText.length; final secondSegment = cleanText.substring(secondSegmentStart, secondSegmentEnd); // 只允许数字 final validSecondSegment = secondSegment.replaceAll(RegExp(r'[^0-9]'), ''); formattedText += validSecondSegment; // 如果第二段长度达到4,添加分隔符并处理第三段(两位数字) if (validSecondSegment.length == 4 && cleanText.length > 6) { formattedText += '-'; final thirdSegmentStart = 6; final thirdSegmentEnd = cleanText.length > 8 ? 8 : cleanText.length; final thirdSegment = cleanText.substring(thirdSegmentStart, thirdSegmentEnd); final validThirdSegment = thirdSegment.replaceAll(RegExp(r'[^0-9]'), ''); formattedText += validThirdSegment; // 如果第三段长度达到2,添加分隔符并处理第四段(四/五位数字) if (validThirdSegment.length == 2 && cleanText.length > 8) { formattedText += '-'; final fourthSegment = cleanText.substring(8); final validFourthSegment = fourthSegment.replaceAll(RegExp(r'[^0-9]'), ''); // 限制第四段最多5位数字 if (validFourthSegment.length > 5) { formattedText += validFourthSegment.substring(0, 5); } else { formattedText += validFourthSegment; } } } } } // 计算光标位置,确保光标始终在正确位置 int cursorPosition = newValue.selection.end; final separatorCount = formattedText.split('-').length - 1; // 光标位置需要加上自动插入的分隔符数量 final originalCleanLength = cleanText.length; final formattedLength = formattedText.length; if (originalCleanLength > oldValue.text.replaceAll('-', '').length) { cursorPosition = formattedLength; } else { // 删除操作时调整光标位置 final oldSeparatorCount = oldValue.text.split('-').length - 1; cursorPosition = newValue.selection.end + (separatorCount - oldSeparatorCount); if (cursorPosition < 0) cursorPosition = 0; } return TextEditingValue( text: formattedText, selection: TextSelection.collapsed(offset: cursorPosition), ); } }
2. 在TextFormField中使用
将自定义的格式化器添加到TextFormField的inputFormatters数组中,同时可以配合keyboardType来优化输入体验:
TextFormField( decoration: const InputDecoration( labelText: '输入编码', hintText: '例如:AB-2121-11-2121', ), inputFormatters: [ CustomCodeFormatter(), ], keyboardType: TextInputType.text, )
代码说明
- 输入清洗:先移除所有已有的
-分隔符,避免重复添加或格式混乱 - 分段验证:每一段分别验证字符类型(前两位仅允许字母,后续仅允许数字),并限制长度
- 自动分隔:当某一段输入达到要求长度时,自动插入
-分隔符 - 光标处理:处理输入和删除操作时的光标位置,确保光标始终处于合理位置
- 长度限制:第四段最多允许5位数字,符合你给出的两种示例格式
这个实现会自动帮用户格式化输入,比如输入AB2121112121会自动变成AB-2121-11-2121,输入到第五位数字时会变成AB-2121-11-21214,同时会过滤掉不符合要求的字符(比如前两位输入数字会被自动忽略)。
内容的提问来源于stack exchange,提问作者Ganesh Chennaiah
相关产品推荐
相关产品推荐

