如何在实时编辑后格式化android EditText中的数字

问题描述 投票:5回答:3

我有一个EditText,其中用户应该输入一个包含小数的数字,我想要一个千位分隔符自动添加到输入数字我尝试了几个其他方法但有些不允许浮点数,所以我想出了这个代码有效只是字符串输入没有被实时编辑成可能有千位分隔符的字符串输入,并且错误似乎源于s.replace();

    am2 = new TextWatcher(){
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }
    public void onTextChanged(CharSequence s, int start, int before, int count) {}
    public void afterTextChanged(Editable s) {
        if (s.toString().equals("")) {
            amount.setText("");
            value = 0;
        }else{
            StringBuffer strBuff = new StringBuffer();
            char c;
            for (int i = 0; i < amount2.getText().toString().length() ; i++) {
                c = amount2.getText().toString().charAt(i);
                if (Character.isDigit(c)) {
                    strBuff.append(c);
                }
            }
            value = Double.parseDouble(strBuff.toString());
            reverse();
            NumberFormat nf2 = NumberFormat.getInstance(Locale.ENGLISH);
            ((DecimalFormat)nf2).applyPattern("###,###.#######");
            s.replace(0, s.length(), nf2.format(value));
        }
    }
};
android android-edittext number-formatting
3个回答
34
投票

此类解决了问题,允许十进制输入并添加千位分隔符。

public class NumberTextWatcher implements TextWatcher {

private DecimalFormat df;
private DecimalFormat dfnd;
private boolean hasFractionalPart;

private EditText et;

public NumberTextWatcher(EditText et)
{
    df = new DecimalFormat("#,###.##");
    df.setDecimalSeparatorAlwaysShown(true);
    dfnd = new DecimalFormat("#,###");
    this.et = et;
    hasFractionalPart = false;
}

@SuppressWarnings("unused")
private static final String TAG = "NumberTextWatcher";

public void afterTextChanged(Editable s)
{
    et.removeTextChangedListener(this);

    try {
        int inilen, endlen;
        inilen = et.getText().length();

        String v = s.toString().replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
        Number n = df.parse(v);
        int cp = et.getSelectionStart();
        if (hasFractionalPart) {
            et.setText(df.format(n));
        } else {
            et.setText(dfnd.format(n));
        }
        endlen = et.getText().length();
        int sel = (cp + (endlen - inilen));
        if (sel > 0 && sel <= et.getText().length()) {
            et.setSelection(sel);
        } else {
            // place cursor at the end?
            et.setSelection(et.getText().length() - 1);
        }
    } catch (NumberFormatException nfe) {
        // do nothing?
    } catch (ParseException e) {
        // do nothing?
    }

    et.addTextChangedListener(this);
}

public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}

public void onTextChanged(CharSequence s, int start, int before, int count)
{
    if (s.toString().contains(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator())))
    {
        hasFractionalPart = true;
    } else {
        hasFractionalPart = false;
    }
}

}

资料来源:http://blog.roshka.com/2012/08/android-edittext-with-number-format.html


3
投票

你需要使用DecimalFormat类与DecimalFormatSymbols类,检查以下方法,

public static String formatAmount(int num) 
{
    DecimalFormat decimalFormat = new DecimalFormat();
    DecimalFormatSymbols decimalFormateSymbol = new DecimalFormatSymbols();
    decimalFormateSymbol.setGroupingSeparator(',');
    decimalFormat.setDecimalFormatSymbols(decimalFormateSymbol);
    return decimalFormat.format(num);
}

1
投票

不幸的是,代码无法正常运行。

它有两个问题:

  1. 如果电话语言环境配置使用“,”作为小数分隔符,则它不起作用。
  2. 如果数字在小数部分中有尾随零,则它不起作用。例1.01。

我疯了解决它。最后,我来到这个在我的手机上运行良好的代码:

number text watcher.Java

import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.Log;
import android.widget.EditText;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;


public class NumberTextWatcher
        implements TextWatcher {

    private static final String TAG = "NumberTextWatcher";

    private final int numDecimals;
    private String groupingSep;
    private String decimalSep;
    private boolean nonUsFormat;
    private DecimalFormat df;
    private DecimalFormat dfnd;
    private boolean hasFractionalPart;

    private EditText et;
    private String value;


    private String replicate(char ch, int n) {
        return new String(new char[n]).replace("\0", "" + ch);
    }

    public NumberTextWatcher(EditText et, Locale locale, int numDecimals) {

        et.setKeyListener(DigitsKeyListener.getInstance("0123456789.,"));
        this.numDecimals = numDecimals;
        DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);

        char gs = symbols.getGroupingSeparator();
        char ds = symbols.getDecimalSeparator();
        groupingSep = String.valueOf(gs);
        decimalSep = String.valueOf(ds);

        String patternInt = "#,###";
        dfnd = new DecimalFormat(patternInt, symbols);

        String patternDec = patternInt + "." + replicate('#', numDecimals);
        df = new DecimalFormat(patternDec, symbols);
        df.setDecimalSeparatorAlwaysShown(true);
        df.setRoundingMode(RoundingMode.DOWN);

        this.et = et;
        hasFractionalPart = false;

        nonUsFormat = !decimalSep.equals(".");
        value = null;

    }


    @Override
    public void afterTextChanged(Editable s) {
        Log.d(TAG, "afterTextChanged");
        et.removeTextChangedListener(this);

        try {
            int inilen, endlen;
            inilen = et.getText().length();

            String v = value.replace(groupingSep, "");

            Number n = df.parse(v);

            int cp = et.getSelectionStart();
            if (hasFractionalPart) {
                int decPos = v.indexOf(decimalSep) + 1;
                int decLen = v.length() - decPos;
                if (decLen > numDecimals) {
                    v = v.substring(0, decPos + numDecimals);
                }
                int trz = countTrailingZeros(v);

                StringBuilder fmt = new StringBuilder(df.format(n));
                while (trz-- > 0) {
                    fmt.append("0");
                }
                et.setText(fmt.toString());
            } else {
                et.setText(dfnd.format(n));
            }


            endlen = et.getText().length();
            int sel = (cp + (endlen - inilen));
            if (sel > 0 && sel <= et.getText().length()) {
                et.setSelection(sel);
            } else {
                // place cursor at the end?
                et.setSelection(et.getText().length() - 1);
            }


        } catch (NumberFormatException | ParseException nfe) {
            // do nothing?
        }


        et.addTextChangedListener(this);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        Log.d(TAG, "beforeTextChanged");
        value = et.getText().toString();
    }

    private int countTrailingZeros(String str) {
        int count = 0;

        for (int i = str.length() - 1; i >= 0; i--) {
            char ch = str.charAt(i);
            if ('0' == ch) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        Log.d(TAG, "onTextChanged");

        String newValue = s.toString();
        String change = newValue.substring(start, start + count);
        String prefix = value.substring(0, start);
        String suffix = value.substring(start + before);

        if (".".equals(change) && nonUsFormat) {
            change = decimalSep;
        }

        value = prefix + change + suffix;
        hasFractionalPart = value.contains(decimalSep);

        Log.d(TAG, "VALUE: " + value);


    }

}

然后用它来做:

    Locale locale = new Locale("es", "AR"); // For example Argentina
    int numDecs = 2; // Let's use 2 decimals
    TextWatcher tw = new NumberTextWatcher(myEditText, locale, numDecs);
    myEditText.addTextChangedListener(tw);
© www.soinside.com 2019 - 2024. All rights reserved.