Flutter支付金额TextField:千分位分隔及小数两位限制问题
Flutter TextField 实现千分位分隔+小数点后两位限制(解决多格式化器冲突问题)
解决方案
1. 修改千分位格式化器,兼容小数处理
原格式化器仅处理整数部分,未考虑小数点逻辑,且无法和其他格式化器兼容。调整后可同时处理整数千分位分隔和小数位限制:
class ThousandsSeparatorInputFormatter extends TextInputFormatter { static const separator = ','; @override TextEditingValue formatEditUpdate( TextEditingValue oldValue, TextEditingValue newValue) { // 空值直接返回 if (newValue.text.isEmpty) { return newValue.copyWith(text: ''); } // 移除已有分隔符,分离整数和小数部分 String cleanValue = newValue.text.replaceAll(separator, ''); List<String> valueParts = cleanValue.split('.'); // 限制小数部分最多两位 if (valueParts.length > 1) { if (valueParts[1].length > 2) { valueParts[1] = valueParts[1].substring(0, 2); } } // 处理整数部分的千分位分隔 String integerPart = valueParts[0]; String formattedInteger = ''; for (int i = integerPart.length - 1; i >= 0; i--) { if ((integerPart.length - 1 - i) % 3 == 0 && i != integerPart.length - 1) { formattedInteger = separator + formattedInteger; } formattedInteger = integerPart[i] + formattedInteger; } // 拼接整数与小数部分 String formattedText = formattedInteger; if (valueParts.length > 1 && valueParts[1].isNotEmpty) { formattedText += '.${valueParts[1]}'; } // 计算光标位置,避免因分隔符添加/删除导致错位 int originalCursorPos = newValue.selection.end; int newSeparatorCount = formattedText.substring(0, originalCursorPos).split(separator).length - 1; int oldSeparatorCount = newValue.text.substring(0, originalCursorPos).split(separator).length - 1; int adjustedCursorPos = originalCursorPos + (newSeparatorCount - oldSeparatorCount); adjustedCursorPos = adjustedCursorPos.clamp(0, formattedText.length); return TextEditingValue( text: formattedText, selection: TextSelection.collapsed(offset: adjustedCursorPos), ); } }
2. 正确配置TextField的inputFormatters
格式化器执行顺序至关重要,需先过滤非法输入,再应用千分位格式化:
TextField( keyboardType: TextInputType.numberWithOptions(decimal: true), controller: controller, inputFormatters: [ // 仅允许输入数字和小数点,同时限制小数位最多两位 FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,2}')), // 千分位格式化器放在最后,基于合法输入处理分隔符 ThousandsSeparatorInputFormatter(), ], decoration: InputDecoration( labelText: '支付金额', ), )
核心注意点
- 顺序优先级:先通过过滤规则确保输入合法,再执行千分位格式化,避免非法字符干扰分隔逻辑。
- 光标适配:格式化器内计算光标偏移量,保证输入/删除操作时光标位置正确。
- 小数限制:在格式化器内直接处理小数位截断,配合过滤规则双重保障输入合规。
内容的提问来源于stack exchange,提问作者user22362195
相关产品推荐
相关产品推荐

