安卓EditText-实现输入小数点后几位的逻辑演变

简介

在Android开发中,时不时需要用户输入一些数据,有输入就有格式上的要求。比如EditText输入金额时,通常要保留小数点后两位,这个如何实现呢?

首先在布局文件里,通过android:inputType限定EditText输入的内容,numberDecimal表示只能输入带小数点的浮点格式

                

EditText inputType属性详解 传送门

方法一,普通实现

给EditText添加TextChangedListener监听,重写onTextChanged方法,输入小数点后两位的逻辑

       @Override
       public void onTextChanged(CharSequence s, int start, int before,
                                  int count) {
            if (s.toString().contains(".")) {
                if (s.length() - 1 - s.toString().indexOf(".") > 2) {
                    s = s.toString().subSequence(0,
                            s.toString().indexOf(".") + 3);
                    editText.setText(s);
                    editText.setSelection(s.length());
                }
            }
            if (s.toString().trim().substring(0).equals(".")) {
                s = "0" + s;
                editText.setText(s);
                editText.setSelection(2);
            }

            if (s.toString().startsWith("0")
                    && s.toString().trim().length() > 1) {
                if (!s.toString().substring(1, 2).equals(".")) {
                    editText.setText(s.subSequence(0, 1));
                    editText.setSelection(1);
                    return;
                }
            }
        }

这种方法实现复杂,有没有更简单的?

方法二,简洁实现

在重写onTextChanged方法里,一旦输入的内容里包含了“.”,则限定输入的文本长度为小数点所在长度加上后两位的长度。把问题转为如何限定EditText输入的内容长度呢?EditText提供了setFilter()方法,InputFilter.LengthFilter类,实现代码如下:

private static final int DEFAULT_MAX_INTEGER_LENGTH = 10;
private static final int DEFAULT_DECIMAL_NUMBER = 2;

private static final InputFilter[] INPUT_FILTER_ARRAY = new InputFilter[1];

/**
 * 保留小数点后多少位
 */
private int mDecimalNumber = DEFAULT_DECIMAL_NUMBER;
/**
 * 允许最大的整数多少位
 */
private int mMaxIntegralLength = DEFAULT_MAX_INTEGER_LENGTH;


@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
    super.onTextChanged(text, start, lengthBefore, lengthAfter);
    if(text.length() > 0) {
        String inputContent = text.toString();
        if (inputContent.contains(".")) {
            int maxLength = inputContent.indexOf(".") + mDecimalNumber + 1;
            INPUT_FILTER_ARRAY[0] = new InputFilter.LengthFilter(maxLength);
        } else {
            INPUT_FILTER_ARRAY[0] = new InputFilter.LengthFilter(mMaxIntegralLength);
        }
        setFilters(INPUT_FILTER_ARRAY);
    }
}

与方法一相比,方法二执行效率得到了提高,不必截取字符串长度subString,同时逻辑上也简化了

方法三,优雅实现

查阅InputFilter,对该类的描述:

InputFilters can be attached to Editables to constrain the changes that can be made to them

InputFilter能过滤EditText的输入内容,如此就不必监听OnTextChangeListener,而是设置过滤器的过滤逻辑,优雅得实现显示小数点后几位,核心代码如下:

setFilters(new InputFilter[]{new InputFilter() {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            String lastInputContent = dest.toString();
            if (lastInputContent.contains(".")) {
                int index = lastInputContent.indexOf(".");
                if(dend - index >= mDecimalNumber + 1){
                    return "";
                }
            }
            return null;
        }
    }});

filter方法用到的入参说明:

  • source 单次输入的字符内容
  • dest上次输入的内容

到此,一个输入小数点后几位的自定义控件雏形已经显现了。

二 简单的自定义控件DecimalEditText,实现输入小数点后若干位

所有代码如下:

public class DecimalEditText extends EditText {

private static final int DEFAULT_DECIMAL_NUMBER = 2;
/**
 * 保留小数点后多少位
 */
private int mDecimalNumber = DEFAULT_DECIMAL_NUMBER;


public DecimalEditText(Context context) {
    this(context,null,R.attr.editTextStyle);
}

public DecimalEditText(Context context, AttributeSet attrs) {
    this(context,attrs, R.attr.editTextStyle);
}

public DecimalEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DecimalEditText);
    mDecimalNumber = typedArray.getInt(R.styleable.DecimalEditText_decimalNumber,DEFAULT_DECIMAL_NUMBER);
    typedArray.recycle();

    init();
}

private void init(){
    setFilters(new InputFilter[]{new InputFilter() {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            String lastInputContent = dest.toString();

            if (source.equals(".") && lastInputContent.length() == 0) {
                return "0.";
            }
            if (lastInputContent.contains(".")) {
                int index = lastInputContent.indexOf(".");
                if(dend - index >= mDecimalNumber + 1){
                    return "";
                }
            }
            return null;
        }
    }});
}

public int getDecimalNumber() {
    return mDecimalNumber;
}

public void setDecimalNumber(int decimalNumber) {
    mDecimalNumber = decimalNumber;
}

}

attr文件


    

小结

方法一的实现思路和网络上搜到的实现差不多,从方法一到方法三,是一个解决问题的逻辑演变的过程。

你可能感兴趣的:(安卓EditText-实现输入小数点后几位的逻辑演变)