Flutter自定义文本编辑控制器:波斯数字显示与setter未被调用问题
解决自定义TextEditingController显示波斯数字、返回英文数字的问题
问题根源
你重写的text setter未被触发,因为TextField在处理用户输入时,直接操作的是controller的value属性,而非调用text setter,导致输入的数字无法转换为波斯数字显示。
解决方案
重写value的setter,在更新值时自动将文本中的英文数字转为波斯数字;同时保留text getter,将显示的波斯数字转回英文数字供外部获取。
1. 定义数字转换扩展方法
如果还未实现数字转换逻辑,先添加以下扩展:
extension StringNumberExtensions on String { // 英文数字转波斯数字 String get toPersianNumbers { const englishDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']; String result = this; for (int i = 0; i < englishDigits.length; i++) { result = result.replaceAll(englishDigits[i], persianDigits[i]); } return result; } // 波斯数字转英文数字 String get toEnglishNumbers { const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']; const englishDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; String result = this; for (int i = 0; i < persianDigits.length; i++) { result = result.replaceAll(persianDigits[i], englishDigits[i]); } return result; } }
2. 修改自定义TextEditingController
class PersianTextEditingController extends TextEditingController { @override String get text => value.text.toEnglishNumbers; @override set value(TextEditingValue newValue) { // 将输入文本中的英文数字转为波斯数字 final persianText = newValue.text.toPersianNumbers; // 保持光标和选区位置不变(数字替换长度一致,无需调整) super.value = TextEditingValue( text: persianText, selection: newValue.selection, composing: newValue.composing, ); } factory PersianTextEditingController({String? text}) => PersianTextEditingController._(text: text); PersianTextEditingController._({String? text}) { // 初始化时转换初始文本 super.value = TextEditingValue( text: (text ?? '').toPersianNumbers, selection: const TextSelection.collapsed(offset: -1), composing: TextRange.empty, ); } }
核心逻辑说明
- 显示层:每次TextField更新
value时,valuesetter会自动将输入的英文数字转为波斯数字,确保界面显示波斯数字。 - 数据层:外部调用
controller.text时,textgetter会将显示的波斯数字转回英文数字,满足业务获取需求。 - 光标处理:由于数字是一对一替换,文本长度不变,光标和选区位置无需额外调整,输入体验不受影响。
内容的提问来源于stack exchange,提问作者Morteza Mohammadi
相关产品推荐
相关产品推荐

