InputFilter实现EditText过滤中文字符、空格等特殊字符

来源:互联网 发布:淘宝网店详情页制作 编辑:程序博客网 时间:2024/05/22 10:15

最近项目要求EditText输入文字时过滤掉中文字符、空格等特殊字符,上网查了好多资料,最后决定使用IputFilter来实现这一功能,写一篇博客来记录一下自己的心得

先上效果图
这里写图片描述

主要代码

public class NoMenuEditText extends EditText {    private final Context context;    private int maxLength;//自定义属性判断是输入字符的最大长度    private boolean allow_blank;//自定义属性判断是否允许输入空格,默认false    private boolean allow_chinese;//自定义属性判断是否允许输入中文    public NoMenuEditText(Context context, AttributeSet attrs) {        super(context, attrs);        this.context = context;        init(attrs);    }    public NoMenuEditText(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.context = context;        init(attrs);    }    private void init(AttributeSet attrs) {        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NoMenuEditText);//加载自定义styleable文件        maxLength = a.getInteger(R.styleable.NoMenuEditText_maxLength,0);//读取自定义属性输入字符的最大长度        allow_blank = a.getBoolean(R.styleable.NoMenuEditText_allow_blank, false);//读取自定义属性是否允许输入空格        allow_chinese = a.getBoolean(R.styleable.NoMenuEditText_allow_chinese,false);//读取自定义属性是否允许输入中文        if (maxLength > 0){            setFilters(new InputFilter[]{new LengthFilter(maxLength),new InputFilter() {                @Override                public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {                    if (!allow_blank){                        if (source.equals(" ")) {                            return "";                        }                    }                    if (!allow_chinese){                        if (checkNameChese(source.toString())){                            return "";                        }                    }                    return null;                }            }});        }else {            setFilters(new InputFilter[]{new InputFilter() {                @Override                public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {                    if (!allow_blank){                        if (source.equals(" ")) {                            return "";                        }                    }                    if (!allow_chinese){                        if (checkNameChese(source.toString())){                            return "";                        }                    }                    return null;                }            }});        }        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());        this.setLongClickable(false);    }    private class ActionModeCallbackInterceptor implements ActionMode.Callback {        private final String TAG = NoMenuEditText.class.getSimpleName();        @Override        public boolean onCreateActionMode(ActionMode mode, Menu menu) {            return false;        }        @Override        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {            return false;        }        @Override        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {            return false;        }        @Override        public void onDestroyActionMode(ActionMode mode) {        }    }    public boolean stringFilter(String str){        // 只允许字母、数字和汉字        String   regEx  =  "[^\u4E00-\u9FA5]";        Pattern   p   =   Pattern.compile(regEx);        Matcher m   =   p.matcher(str);        return   m.matches();    }    /**     * 判定输入汉字     * @param c     * @return     */    public  boolean isChinese(char c) {        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {            return true;        }        return false;    }    /**     * 检测String是否全是中文     * @param name     * @return     */    public  boolean checkNameChese(String name)    {        boolean res=false;        char [] cTemp = name.toCharArray();        for(int i=0;i<name.length();i++)        {            if(isChinese(cTemp[i]))            {                res=true;                break;            }        }        return res;    }}

自定义属性文件在attrs.xml文件中

<declare-styleable name="NoMenuEditText">        <attr name="allow_blank" format="boolean" />        <attr name="maxLength" format="integer" />        <attr name="allow_chinese" format="boolean" />    </declare-styleable>

XML布局中的使用方式

<com.xfzd.client.user.view.NoMenuEditText                xmlns:aa="http://schemas.android.com/apk/res-auto/com.xfzd.client"                aa:allow_blank="true"                aa:maxLength="20"

代码分析

上述代码8-11,14-18分别是自定义EditText构造函数当中都有一个初始化init(attrs)方法,我们在此方法中实现自定义属性的解析,和自定义InputFilter过滤器的实现

这里写图片描述
20行代码,可能到家会对自定义属性maxLength感到疑惑,因为EditText有一个属性android:maxLength=”19”为什么这里还要设置一个自定义属性,岂不是多此一举,我子啊这里要解释一下android:maxLength=”19”这个属性是在EditText的父类也就是TextView中使用到的,我们进入到TextView的代码中我们看一看
这里写图片描述
这行代码实在TextView的构造函数中,其中maxLength就是解析TextView属性android:maxLength的到的值,我们在这里可以看到此处会根据maxLength的长度来用不同的策略来设置InputFilters这个数组,最后在通过setFilters()这个方法去设置TextView的过滤器,我们看到maxLength长度大于0时,会给InputFilter[]数组设置一个成员new InputFilter.LengthFilter(maxlength) TextView和EidtText正是由于设置了这样一个InputFilter才实现文字长度的限制
这里写图片描述
进入到LengthFilter的源码中我们发现LengthFilter 实现了 InputFilter这个接口并实现了filter()这个方法,因此才能实现对TextView、EditText的字符长度的限制。我门今天实现的就是通过自定InputFilter实现EditText过滤中文、空格等特殊字符,而这其中的关键也是在于实现InputFilter接口通过实现filter()这个方法,来达到实现字符的过滤

我们还是从最关键的地方Init函数分析

private void init(AttributeSet attrs) {        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NoMenuEditText);//加载自定义styleable文件        maxLength = a.getInteger(R.styleable.NoMenuEditText_maxLength,0);//读取自定义属性输入字符的最大长度        allow_blank = a.getBoolean(R.styleable.NoMenuEditText_allow_blank, false);//读取自定义属性是否允许输入空格        allow_chinese = a.getBoolean(R.styleable.NoMenuEditText_allow_chinese,false);//读取自定义属性是否允许输入中文        if (maxLength > 0){            setFilters(new InputFilter[]{new LengthFilter(maxLength),new InputFilter() {                @Override                public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {                    if (!allow_blank){                        if (source.equals(" ")) {                            return "";                        }                    }                    if (!allow_chinese){                        if (checkNameChese(source.toString())){                            return "";                        }                    }                    return null;                }            }});        }else {            setFilters(new InputFilter[]{new InputFilter() {                @Override                public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {                    if (!allow_blank){                        if (source.equals(" ")) {                            return "";                        }                    }                    if (!allow_chinese){                        if (checkNameChese(source.toString())){                            return "";                        }                    }                    return null;                }            }});        }        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());        this.setLongClickable(false);    }

6行判断maxLength 属性是否大于0(默认为0,大于0说明在布局xml中view的属性中设置过),接下来第7行setFilters(new InputFilter[])我们看到该方法的参数是一个InputFilter[]数组,实际上就是说可以通过多组合InputFilter来实现各种过滤的效果,我们实现的就是过滤中文字符和空字符串,所以我在数组的第二个变量中重写InputFilter的filter方法来实现这样的效果。filter过滤是通过返回值来决定的

  1. return “”
    表示过滤输入的内容
  2. return null
    表示不过滤输入的内容

我们看10行先判断是不允许输入空字符串,进入11行判断输入内容是为空字符串过滤,15行判断不允许输入中文进入16行判断输入内容为中文字符过滤,否则进入20行不进行过滤

0 0
原创粉丝点击