Flutter Intl库数字格式化:输入错位与光标异常问题求助
解决Flutter Intl格式化千位分隔符时的输入异常与光标问题
修正后的代码
final TextEditingController kcalEditingController = TextEditingController(); bool _isFormatting = false; // 标记是否正在格式化,避免循环触发 @override void initState() { super.initState(); kcalEditingController.addListener(_handleTextFormatting); } void _handleTextFormatting() { if (_isFormatting) return; // 正在格式化时跳过,防止循环触发 final rawText = kcalEditingController.text.replaceAll(RegExp('[.,]'), ''); if (rawText.length <= 3) return; // 少于4位不需要格式化 _isFormatting = true; try { final numberFormat = NumberFormat.decimalPattern(Platform.localeName); final formattedText = numberFormat.format(int.parse(rawText)); // 计算光标应该在的位置:原光标位置减去被移除的分隔符数量,再加上新添加的分隔符数量 final originalCursorPosition = kcalEditingController.selection.baseOffset; final originalSeparatorCount = kcalEditingController.text.length - rawText.length; final newSeparatorCount = formattedText.length - rawText.length; int newCursorPosition = originalCursorPosition - originalSeparatorCount + newSeparatorCount; // 确保光标位置不越界 newCursorPosition = newCursorPosition.clamp(0, formattedText.length); // 更新文本和光标位置 kcalEditingController.value = TextEditingValue( text: formattedText, selection: TextSelection.collapsed(offset: newCursorPosition), ); } finally { _isFormatting = false; // 格式化完成后重置标记 } } @override void dispose() { kcalEditingController.removeListener(_handleTextFormatting); kcalEditingController.dispose(); super.dispose(); }
关键问题解析与解决要点
- 循环触发监听:直接修改
text会再次触发控制器的listener,导致重复格式化。通过_isFormatting标志位,在格式化过程中跳过监听逻辑,避免无限循环。 - 光标位置错乱:格式化后默认光标会跳到文本开头,需要手动计算新的光标位置:先统计原文本的分隔符数量,再对比格式化后的分隔符数量,调整光标偏移量,确保光标停留在用户输入的位置附近。
- 输入字符错位:之前的逻辑没有处理光标位置,导致新输入的字符被插入到错误位置。通过
TextEditingValue同时设置文本和光标位置,保证输入的字符出现在正确位置。 - 输入无响应:当输入0时,原逻辑中
text.length可能因为分隔符的存在没有正确增加,导致不触发格式化。现在改为判断纯数字的长度,确保所有有效数字输入都能被处理。
内容的提问来源于stack exchange,提问作者WizardingStudios
相关产品推荐
相关产品推荐

