如何使用TextWatcher实现EditText从右到左的金额自动格式化?
实现PayPal风格的EditText自动小数格式化
这个需求我之前做支付类应用时正好遇到过,用TextWatcher完全能搞定核心逻辑——把用户输入的每一位数字当作分来处理,自动转换成保留两位小数的“元”格式,完美匹配你要的效果。
核心思路
用户输入的数字序列其实是总分数:
- 输入
1→ 1分 → 0.01元 - 输入
11→ 11分 → 0.11元 - 输入
222→ 222分 → 2.22元
为了避免setText触发TextWatcher的循环调用,我们需要加一个状态标志位;同时维护一个纯数字字符串来跟踪用户的真实输入(避免从格式化后的带小数点文本里提取数字的麻烦)。
完整代码实现
替换你现有的EditTextListener,用下面的版本:
private class EditTextListener implements TextWatcher { // 保存用户输入的纯数字序列 private String currentDigits = ""; // 防止setText触发循环更新的标志位 private boolean isUpdating = false; // 确保输出格式始终是两位小数 private final DecimalFormat decimalFormat = new DecimalFormat("0.00"); @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // 不需要额外处理 } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (isUpdating) return; // 处理用户输入字符:追加纯数字到currentDigits if (count > 0) { String input = s.subSequence(start, start + count).toString(); // 过滤掉非数字字符(防止意外输入) input = input.replaceAll("[^0-9]", ""); currentDigits += input; } // 处理用户删除字符:从currentDigits末尾截断 else if (before > 0) { if (currentDigits.length() >= before) { currentDigits = currentDigits.substring(0, currentDigits.length() - before); } else { currentDigits = ""; } } } @Override public void afterTextChanged(Editable s) { if (isUpdating) return; isUpdating = true; if (currentDigits.isEmpty()) { // 无输入时重置为默认的0.00 editText.setText("0.00"); // 光标定位到小数点前,方便继续输入 editText.setSelection(1); } else { try { // 将数字转为分,再除以100得到元 long cents = Long.parseLong(currentDigits); BigDecimal amount = BigDecimal.valueOf(cents).divide(BigDecimal.valueOf(100)); String formattedText = decimalFormat.format(amount); editText.setText(formattedText); // 光标固定在小数点前的数字末尾,保持输入流畅性 int cursorPos = formattedText.indexOf(".") - 1; editText.setSelection(Math.max(cursorPos, 0)); } catch (NumberFormatException e) { // 处理数字过大溢出的情况,重置为默认值 editText.setText("0.00"); currentDigits = ""; editText.setSelection(1); } } isUpdating = false; } }
额外优化建议
- XML输入类型限制:为EditText设置
inputType="number",让系统弹出纯数字键盘,避免用户输入非数字字符:
<EditText android:id="@+id/editText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="number" android:text="0.00" />
- 大数处理:如果需要支持超过
Long范围的数字(比如超长金额),可以把Long.parseLong换成BigInteger来处理:
BigInteger cents = new BigInteger(currentDigits); BigDecimal amount = new BigDecimal(cents).divide(BigDecimal.valueOf(100));
效果验证
- 初始状态:显示
0.00,光标在0和.之间 - 输入
1→ 显示0.01 - 再输入
1→ 显示0.11 - 再输入
2→ 显示1.12 - 删除一次 → 回到
0.11 - 删除至空 → 重置为
0.00
内容的提问来源于stack exchange,提问作者Félix Maroy
相关产品推荐
相关产品推荐

