You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EditText的onTextChanged()功能异常,金额逐位格式化需求未实现

解决EditText金额格式化(0.00→0.02→0.23→2.35)的问题

你想要实现的是一种类似金额输入的实时格式化效果,初始显示0.00,每输入一位数字就将现有数字左移一位并替换最后一位,最终达到输入数字依次进位的效果对吧?你的当前代码无法更新EditText,主要有几个核心问题,我来帮你梳理并修复:

现有代码的问题分析

  • TextWatcher循环回调问题:在onTextChanged中直接调用text.setText()会再次触发TextWatcher的回调,导致逻辑混乱,甚至可能引发栈溢出,而且你没有处理这种循环触发的情况。
  • counter变量逻辑错误:counter只在每次输入时自增,但没有考虑删除操作,且判断条件依赖counter的固定值,无法适配多次输入或修改的场景。
  • 字符处理逻辑偏差:你错误地通过s.length()>=5来判断输入,并且取s.charAt(4)的方式不符合需求逻辑,应该聚焦于每次输入的新数字,而非固定位置的字符。
  • 初始数组处理问题:基于初始字符串生成的amount数组没有正确对应无小数点的数字位,导致后续移位逻辑出错。

修正后的解决方案

下面是修复后的代码,我会在代码后解释关键改动:

public class MainActivity extends Activity {
    private EditText text;
    // 用字符串存储无小数点的数字位,初始是"000"对应0.00
    private String numberStr = "000";
    private TextWatcher textWatcher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = findViewById(R.id.text);
        // 初始设置为0.00
        text.setText("0.00");
        // 设置光标到末尾
        text.setSelection(text.getText().length());

        textWatcher = 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) {
                // 避免循环回调:如果当前显示的是格式化后的内容,直接返回
                String currentText = s.toString();
                if (currentText.equals(formatNumberStr())) {
                    return;
                }

                // 提取用户输入的最后一个数字(过滤非数字字符)
                String input = currentText.replaceAll("[^0-9]", "");
                if (input.length() == 0) {
                    // 没有有效数字,重置为000
                    numberStr = "000";
                    updateEditText();
                    return;
                }

                // 取最后一位输入的数字
                char lastInput = input.charAt(input.length() - 1);
                // 左移数字位:去掉第一位,加上新输入的数字
                numberStr = numberStr.substring(1) + lastInput;
                // 更新EditText显示
                updateEditText();
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        };

        text.addTextChangedListener(textWatcher);
    }

    // 将numberStr格式化为带小数点的字符串(xxx → x.xx)
    private String formatNumberStr() {
        return numberStr.substring(0, 1) + "." + numberStr.substring(1);
    }

    // 更新EditText,避免循环回调
    private void updateEditText() {
        text.removeTextChangedListener(textWatcher);
        text.setText(formatNumberStr());
        // 光标始终保持在末尾
        text.setSelection(text.getText().length());
        text.addTextChangedListener(textWatcher);
    }
}

关键改动说明

  1. 避免循环回调:在updateEditText方法中,先移除TextWatcher,设置文本后再重新添加,这样就不会因为setText触发重复回调。
  2. 简化数字处理逻辑:用numberStr存储无小数点的三位数字(初始"000"),每次输入新数字时,直接去掉第一位,将新数字添加到末尾,再格式化为带小数点的字符串。
  3. 过滤非数字输入:通过replaceAll("[^0-9]", "")提取有效数字,避免用户输入非数字字符导致逻辑出错。
  4. 光标位置保持:每次更新文本后都将光标设置到末尾,提升用户输入体验。

这样修改后,就能完美实现你想要的效果:初始显示0.00,输入2→0.02,输入3→0.23,输入5→2.35,后续输入也会继续左移进位。

内容的提问来源于stack exchange,提问作者Rajitha Perera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:03:26