java[android]中带3位小数的EditText掩码

java[android]中带3位小数的EditText掩码,java,android,android-edittext,masking,textwatcher,Java,Android,Android Edittext,Masking,Textwatcher,我是Android的新手,我想为EditText做一个掩码,它的小数点为3位(例如:0.658),我需要一个用户不需要写“.”的掩码,只需要数字,就像传统的货币掩码一样 我正在尝试创建一个基于以下内容的TextWatcher: public static TextWatcher currency(final EditText editText) { return new TextWatcher() { String current = ""; publi

我是Android的新手,我想为EditText做一个掩码,它的小数点为3位(例如:0.658),我需要一个用户不需要写“.”的掩码,只需要数字,就像传统的货币掩码一样

我正在尝试创建一个基于以下内容的TextWatcher:

public static TextWatcher currency(final EditText editText) {
    return new TextWatcher() {
        String current = "";

        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (!s.toString().equals(current)) {
                editText.removeTextChangedListener(this);

                String cleanString = s.toString();

                if(count != 0) {
                    String substr = cleanString.substring(cleanString.length() - 2);

                    if (substr.contains(".") || substr.contains(",")) {
                        cleanString += "0";
                    }
                }

                cleanString = cleanString.replaceAll("[R$,.]", "");

                double parsed = Double.parseDouble(cleanString);
                Locale locale = new Locale("pt", "BR");
                String formatted = NumberFormat.getCurrencyInstance(locale).format((parsed / 100));
                formatted = formatted.replaceAll("[R$]", "");

                current = formatted;
                editText.setText(formatted);
                editText.setSelection(formatted.length());

                editText.addTextChangedListener(this);
            }
        }

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

        public void afterTextChanged(Editable s) {}
    };
}
但是没有成功

有更好的方法吗


谢谢。

尝试从github使用。

我遇到了类似的问题。所以我开始寻找TextWatcher的任何实现。我最终决定建立自己的:

public class BrRealMoneyTextWatcher implements TextWatcher {

    private static final Locale DEFAULT_LOCALE = new Locale("pt", "BR");

    private static DecimalFormat NUMBER_FORMAT = (DecimalFormat) DecimalFormat.getCurrencyInstance(DEFAULT_LOCALE);

    private static final int FRACTION_DIGITS = 2;

    private static final String DECIMAL_SEPARATOR;

    private static final String CURRENCY_SIMBOL;

    static {
        NUMBER_FORMAT.setMaximumFractionDigits(FRACTION_DIGITS);
        NUMBER_FORMAT.setMaximumFractionDigits(FRACTION_DIGITS);
        NUMBER_FORMAT.setParseBigDecimal(true);
        DECIMAL_SEPARATOR = String.valueOf(NUMBER_FORMAT.getDecimalFormatSymbols().getDecimalSeparator());
        CURRENCY_SIMBOL = NUMBER_FORMAT.getCurrency().getSymbol(DEFAULT_LOCALE);
    }

    final EditText target;

    public BrRealMoneyTextWatcher(EditText target) {
        this.target = target;
    }

    private boolean updating = false;

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int after) {
        if (updating) {
            updating = false;
            return;
        }

        updating = true;
        try {
            String valueStr = formatNumber(fixDecimal(s.toString()));
            BigDecimal parsedValue = ((BigDecimal) NUMBER_FORMAT.parse(valueStr));
            String value = NUMBER_FORMAT.format(parsedValue);
            target.setText(value);
            target.setSelection(value.length());
        } catch (ParseException | NumberFormatException ex) {
            throw new IllegalArgumentException("Erro ao aplicar a máscara", ex);
        }
    }

    private String formatNumber(String originalNumber) {
        String number = originalNumber.replaceAll("[^\\d]", "");
        switch(number.length()) {
            case 0 :
                number = "0" + DECIMAL_SEPARATOR + "00";
                break;
            case 1 :
                number = "0" + DECIMAL_SEPARATOR + "0" + number;
                break;
            case 2 :
                number = "0" + DECIMAL_SEPARATOR + number;
                break;
            default:
                number =  number.substring(0, number.length() - 2) + DECIMAL_SEPARATOR + number.substring(number.length() - 2);
                break;
        }
        return CURRENCY_SIMBOL + number;
    }

    private String fixDecimal(String number) {
        int dotPos = number.indexOf('.') + 1;
        int length = number.length();
        return (length - dotPos < FRACTION_DIGITS) ? fixDecimal(number + "0") : number;
    }

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

    @Override
    public void afterTextChanged(Editable s) {
    }
}
public类BrRealMoneyTextWatcher实现TextWatcher{
私有静态最终语言环境默认值_语言环境=新语言环境(“pt”、“BR”);
私有静态DecimalFormat NUMBER_FORMAT=(DecimalFormat)DecimalFormat.getCurrencyInstance(默认语言环境);
私有静态最终整数分数_位数=2;
专用静态最终字符串十进制分隔符;
私有静态最终字符串货币\u SIMBOL;
静止的{
数字格式。设置最大分数位数(分数位数);
数字格式。设置最大分数位数(分数位数);
数字\格式。setParseBigDecimal(真);
DECIMAL_SEPARATOR=String.valueOf(NUMBER_FORMAT.getDecimalFormatSymbols().getDecimalSeparator());
CURRENCY\u SIMBOL=NUMBER\u FORMAT.getCurrency().getSymbol(默认语言环境);
}
最终文本目标;
公共BrRealMoneyTextWatcher(编辑文本目标){
this.target=目标;
}
私有布尔更新=false;
@凌驾
public void onTextChanged(字符序列,int start,int before,int after){
如果(更新){
更新=假;
返回;
}
更新=真;
试一试{
字符串valueStr=formatNumber(fixDecimal(s.toString());
BigDecimal parsedValue=((BigDecimal)NUMBER_FORMAT.parse(valueStr));
字符串值=数字\格式。格式(parsedValue);
target.setText(值);
target.setSelection(value.length());
}catch(ParseException | NumberFormatException ex){
抛出新的非法辩论例外(“错误”和“错误”,例如);
}
}
专用字符串formatNumber(字符串原始编号){
字符串编号=originalNumber.replaceAll(“[^\\d]”,“”);
开关(number.length()){
案例0:
number=“0”+十进制分隔符+“00”;
打破
案例1:
number=“0”+十进制分隔符+“0”+数字;
打破
案例2:
number=“0”+十进制分隔符+数字;
打破
违约:
number=number.substring(0,number.length()-2)+十进制分隔符+number.substring(number.length()-2);
打破
}
返回货币_SIMBOL+编号;
}
私有字符串fixDecimal(字符串编号){
int dotPos=number.indexOf('.')+1;
int length=number.length();
返回值(长度-点位<分数位)?固定小数(数字+“0”):数字;
}
@凌驾
更改前文本之前的公共void(字符序列s、int start、int count、int after){
}
@凌驾
公共无效后文本已更改(可编辑){
}
}
我希望它能帮助别人