Android EditText NumberInputFilter实现整数和小数位数限制

4,175 阅读2分钟

需求背景

很多时候,我们需要实现一个输入金额或者数量的小数数字输入框,要求限制小数最多输入2位,即需要限制整数和小数输入位数。

解决方案

解决办法一般有两种

  • 设置textWatcher,监听输入,如果输入不满足格式要求,则对结果进行处理,重新setText()进行赋值。如下伪代码:

    editText.addTextWatcher(new TextWatcher{
            ...
            afterTextChanged(Editable s){
            //如果输入“.”则自动变为“0.”
                if (".".equals(s.toString())){
                    editText.setText("0.");
                }
                //判断小数点位置,并对长度进行判断拦截
                ...
            }
    })
    

    textWatcher的缺点在于:

    (1)当对输入内容进行了校验和修改后,需要重新持有EditText对象进行setText()。

    (2)另外如果不注意使用,在AdapterView中很容易重复设置textWatcher。

    所以此处更推荐使用InputFilter

  • 设置InputFilter,对输入直接进行处理。
    网络搜索一番,如下是一个比较流行的解决方案:
    stackoverflow.com/questions/3…
    但是这个方案有个很严重的bug:当小数位数达到上限时,无法编辑整数位;整数位数达到上限时,也无法编辑小数位。
    基于这个方案,进行了改进,有了下文的方案:
    先设置了目标正则公式

"[0-9]{0,digitsBeforeZero}+(\\.[0-9]{0,digitsAfterZero})?"

(1)简单解析一下这个正则公式:
[0-9]{0,digitsBeforeZero}+ 表示有0-digitsBeforeZero个0-9的整数;
(\.[0-9]{0,digitsAfterZero})? 表示有0-digitsAfterZero个0-9的小数,小数可有可无。
也就是说,123,123.1,123.12都是符合条件的。
(2)然后对输入进行处理,得到结果值。
如果符合正则公式,则输入成功;如果不符合正则公式,则不允许输入。

public class DecimalDigitsInputFilter implements InputFilter {
    Pattern mPattern;

    public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) {
        String regex = String.format("[0-9]{0,%d}+(\\.[0-9]{0,%d})?", digitsBeforeZero, digitsAfterZero);
        mPattern = Pattern.compile(regex);
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        //直接输入"."返回"0."
        //".x"删除"x"输出为".",inputFilter无法处理成"0.",所以只处理直接输入"."case
        if (".".equals(source) && "".equals(dest.toString())) {
            return "0.";
        }
        StringBuilder builder = new StringBuilder(dest);
        if ("".equals(source)) {
            builder.replace(dstart, dend, "");
        } else {
            builder.insert(dstart, source);
        }
        String resultTemp = builder.toString();
        //判断修改后的数字是否满足小数格式,不满足则返回 "",不允许修改
        Matcher matcher = mPattern.matcher(resultTemp);
        if (!matcher.matches()) {
            return "";
        }
        return null;
    }

}