EditText输入时无法显示波斯/阿拉伯数字,setText()正常,添加监听后崩溃
解决EditText输入时自动转换为波斯/阿拉伯数字的问题
我完全懂你的困扰——用setText()给EditText设置数字时能正常显示波斯/阿拉伯数字,但手动输入时还是跳出英文数字,好不容易加了TextWatcher结果直接崩溃了。这问题我之前也碰到过,核心原因是直接在TextWatcher里修改文本会触发无限循环回调,导致应用崩溃,而且没做光标位置保存的话体验也很差。
下面给你一套靠谱的解决方案:
1. 先写一个数字转换工具方法
首先需要一个能把英文数字(0-9)转换成波斯/阿拉伯数字的工具函数,根据你的需求选对应的Unicode字符:
// 转换为波斯数字(٠١٢٣٤٥٦٧٨٩) public static String convertToPersianDigits(String input) { if (input == null || input.isEmpty()) return input; char[] chars = input.toCharArray(); for (int i = 0; i < chars.length; i++) { if (chars[i] >= '0' && chars[i] <= '9') { // 波斯数字起始Unicode是\u06F0,对应0 chars[i] = (char) (chars[i] - '0' + '\u06F0'); } } return new String(chars); } // 如果需要阿拉伯数字(۰۱۲۳۴۵۶۷۸۹),替换成这个方法 public static String convertToArabicDigits(String input) { if (input == null || input.isEmpty()) return input; char[] chars = input.toCharArray(); for (int i = 0; i < chars.length; i++) { if (chars[i] >= '0' && chars[i] <= '9') { // 阿拉伯数字起始Unicode是\u0660,对应0 chars[i] = (char) (chars[i] - '0' + '\u0660'); } } return new String(chars); }
2. 正确实现TextWatcher(避免崩溃+保留光标)
关键是要加一个标志位,防止修改文本后触发无限循环的afterTextChanged回调,同时保存光标位置,让用户输入体验正常:
// 定义一个全局/成员变量的标志位,控制是否正在更新文本 private boolean isTextUpdating = false; // 给你的EditText设置监听 EditText yourEditText = findViewById(R.id.your_edit_text_id); yourEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // 这里不需要额外处理 } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // 这里也不需要额外处理 } @Override public void afterTextChanged(Editable s) { // 如果正在更新文本,直接返回,避免循环触发 if (isTextUpdating) { return; } isTextUpdating = true; // 1. 获取当前输入的原始文本 String originalText = s.toString(); // 2. 转换为目标数字(选波斯或阿拉伯的方法) String convertedText = convertToPersianDigits(originalText); // 3. 保存当前光标位置,不然转换后光标会跳到末尾 int cursorPos = yourEditText.getSelectionStart(); // 4. 替换文本 s.replace(0, s.length(), convertedText); // 5. 恢复光标位置 yourEditText.setSelection(cursorPos); isTextUpdating = false; } });
3. 补充XML配置(可选但重要)
为了确保用户能正常输入(包括系统键盘的数字和转换后的数字),建议在EditText的XML属性里加上android:digits,允许所有需要的数字字符:
<EditText android:id="@+id/your_edit_text_id" android:layout_width="match_parent" android:layout_height="wrap_content" <!-- 允许英文数字、波斯数字、阿拉伯数字 --> android:digits="0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹" android:inputType="number" />
为什么之前会崩溃?
你之前加了TextWatcher后崩溃,大概率是因为没有设置标志位:每次在afterTextChanged里修改文本,都会再次触发afterTextChanged,形成无限循环,最终导致应用ANR或者崩溃。这个标志位就是用来打断这个循环的。
另外,如果你之前没有保存光标位置,用户输入时光标会一直跳到末尾,体验也会很差,所以这一步也不能少。
内容的提问来源于stack exchange,提问作者mohamad.zamani
相关产品推荐
相关产品推荐

