EditText输入限制:整数,小数,最大值,最大字符长度,手机号

EditText是最常用的控件。很多情况下都要求只能输入特定的字符。比如只能输入整数,只能输入两位小数等。

为了满足EditText输入限制,大体上有两种方法:
- 给EditText加TextWatcher,监听用户输入,如果输入不合法,作相应处理。
- 使用InputFilter。

两种方法都能实现,但感觉第一种方式不太好复用。考虑使用InputFilter的实现。

InputFilters can be attached to Editables to constrain the changes that can be made to them.
(InputFilters可以限制可输入控件的输入)

EditText继承TextView,TextView中有个setFilters方法,这个方法就是设置InputFilters的。需要注意的是,这个方法最好只调用一次,多次调用,只有最后一次才会生效(即会覆盖之前的操作)。

在实际使用中,只要实现InputFilter类,满足各种各样的输入限制就行了。InputFilter只有一个filter方法要实现。该方法有五个参数:
- CharSequence source:刚输入的还没显示出来的字符
- int start与int end:应该是输入字符的位置,输入一个字符时分别是0和1,删除时都是0.
- Spanned dest:已经在EditText中显示出来的字符。
- int dstart, int dend:输入字符要插入和删除的位置。

实现了一个XEditText类,该类继承自AppCompatEditText,实现了多个InputFilter满足输入限制的功能。


import android.content.Context;
import android.support.v7.widget.AppCompatEditText;
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.AttributeSet;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Created by 林下de夕阳 on 2017/4/28.
 * 具有输入限制的EditText
 */

public class XEditText extends AppCompatEditText {

    // 保存设置的所有输入限制
    private List inputFilters;

    public XEditText(Context context) {
        super(context);
        init();
    }

    public XEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public XEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        inputFilters = new ArrayList<>();
    }

    /**
     * 设置允许输入的最大字符数
     */
    public void setMaxLengthFilter(int maxLength) {
        inputFilters.add(new InputFilter.LengthFilter(maxLength));
        setFilters(inputFilters.toArray(new InputFilter[inputFilters.size()]));
    }

    /**
     * 设置可输入小数位
     */
    public void setDecimalFilter(int num) {
        inputFilters.add(new SignedDecimalFilter(0, num));
        setFilters(inputFilters.toArray(new InputFilter[inputFilters.size()]));
    }

    /**
     * 设置最大值
     * @param maxmum  允许的最大值
     * @param numOfDecimal  允许的小数位
     */
    public void setMaxmumFilter(double maxmum, int numOfDecimal) {
        inputFilters.add(new MaxmumFilter(0, maxmum, numOfDecimal));
        setFilters(inputFilters.toArray(new InputFilter[inputFilters.size()]));
    }

    /**
     * 设置只能输入整数
     * @param min 输入整数的最小值
     */
    public void setIntergerFilter(int min) {
        inputFilters.add(new SignedIntegerFilter(min));
        setFilters(inputFilters.toArray(new InputFilter[inputFilters.size()]));
    }

    /**
     * 只能够输入手机号码
     */
    public void setTelFilter() {
        inputFilters.add(new TelephoneNumberInputFilter());
        setFilters(inputFilters.toArray(new InputFilter[inputFilters.size()]));
    }

    /**
     * 小数位数限制
     */
    private static final class SignedDecimalFilter implements InputFilter {

        private final Pattern pattern;

        SignedDecimalFilter(int min, int numOfDecimals) {
            pattern = Pattern.compile("^" + (min < 0 ? "-?" : "")
                    + "[0-9]*\\.?[0-9]" + (numOfDecimals > 0 ? ("{0," + numOfDecimals + "}$") : "*"));
        }

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source.equals(".")) {
                if (dstart == 0 || !(dest.charAt(dstart - 1) >= '0' && dest.charAt(dstart - 1) <= '9') || dest.charAt(0) == '0') {
                    return "";
                }
            }
            if (source.equals("0") && (dest.toString()).contains(".") && dstart == 0) { //防止在369.369的最前面输入0变成0369.369这种不合法的形式
                return "";
            }
            StringBuilder builder = new StringBuilder(dest);
            builder.delete(dstart, dend);
            builder.insert(dstart, source);
            if (!pattern.matcher(builder.toString()).matches()) {
                return "";
            }

            return source;
        }
    }

    /**
     * 限制输入最大值
     */
    private static final class MaxmumFilter implements InputFilter {

        private final Pattern pattern;
        private final double maxNum;

        MaxmumFilter(int min, double maxNum, int numOfDecimals) {
            pattern = Pattern.compile("^" + (min < 0 ? "-?" : "")
                    + "[0-9]*\\.?[0-9]" + (numOfDecimals > 0 ? ("{0," + numOfDecimals + "}$") : "*"));
            this.maxNum = maxNum;
        }

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source.equals(".")) {
                if (dstart == 0 || !(dest.charAt(dstart - 1) >= '0' && dest.charAt(dstart - 1) <= '9') || dest.charAt(0) == '0') {
                    return "";
                }
            }
            if (source.equals("0") && (dest.toString()).contains(".") && dstart == 0) {
                return "";
            }

            StringBuilder builder = new StringBuilder(dest);
            builder.delete(dstart, dend);
            builder.insert(dstart, source);
            if (!pattern.matcher(builder.toString()).matches()) {
                return "";
            }

            if (!TextUtils.isEmpty(builder)) {
                double num = Double.parseDouble(builder.toString());
                if (num > maxNum) {
                    return "";
                }
            }
            return source;
        }
    }

    /**
     * 限制整数
     */
    private static final class SignedIntegerFilter implements InputFilter {
        private final Pattern pattern;

        SignedIntegerFilter(int min) {
            pattern = Pattern.compile("^" + (min < 0 ? "-?" : "") + "[0-9]*$");
        }

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            StringBuilder builder = new StringBuilder(dest);
            builder.insert(dstart, source);
            if (!pattern.matcher(builder.toString()).matches()) {
                return "";
            }
            return source;
        }
    }

    /**
     * 限制电话号码
     */
    private static class TelephoneNumberInputFilter implements InputFilter {

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            StringBuilder builder = new StringBuilder(dest);
            builder.insert(dstart, source);
            int length = builder.length();
            if (length == 1) {
                if (builder.charAt(0) == '1') {
                    return source;
                } else {
                    return "";
                }
            }

            if (length > 0 && length <= 11) {
                int suffixSize = length - 2;
                Pattern pattern = Pattern.compile("^1[3-9]\\d{" + suffixSize + "}$");
                if (pattern.matcher(builder.toString()).matches()) {
                    return source;
                } else {
                    return "";
                }
            }

            return "";
        }
    }
}

你可能感兴趣的:(Android,Android,EditText,输入限制)