美文网首页简化开发
Android EditText 字符过滤

Android EditText 字符过滤

作者: 我啊翔1314 | 来源:发表于2018-07-08 00:00 被阅读0次

    我们使用EditText控件的时候,可能会遇到这样一种情况,在输入的时候,要求禁止输入某些字符。如输入$,#等特殊字符的时候,使其输入无效。这就是字符的过滤。要实现该效果,可以有多种方法,下面将一一介绍:

    1.android:inputType

    这是最常见的一种字符过滤的方法了,通过设置inputType标签属性,可以控制输入内容的类型,如android:inputType="password",这表示输入的内容应该为密码;而android:inputType="text"时,则表示输入的内容是文本。

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="text" />
    

    在java中,则可使用setInputType来设置:

    etText.setInputType(InputType.TYPE_CLASS_TEXT)
    

    2.android:digits

    如果需要更详细的对输入内容进行控制,可使用android:digits属性。只要在该属性设置允许输入的所有字符,就可以达到字符过滤的效果。比如,要让EditText只能输入数字,可以这样写

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:digits="1234567890" />
    

    只能输入数字和英语,则如下

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:digits="1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" />
    

    这样,在点击键盘上的其他字符时(@,#,!等),都不会输入到输入框中。

    3.InputFilter

    如果仅仅是限制几个字符的输入,那么使用android:digits属性就不好进行处理了,因为设置一大堆字符。在这样的情况下,我们可以使用InputFilter来进行字符过滤。在实现InputFilter的时候,需要覆盖InputFilter的filter方法:

    InputFilter filter = new InputFilter() {
      @Override
      public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        return null;
      }
    }
    

    其中的source变量即为输入的字符内容,可以对其进行判断并做处理。如控制不允许输入空格,可以这样写:

    InputFilter filter1 = new InputFilter() {
      @Override
      public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        // 判断是否输入空格
        if (" ".equals(source)) {
          return "";
        }
        return null;
      }
    }
    

    禁止输入多种特殊字符,如下:

    InputFilter filter2 = new InputFilter() {
      @Override
      public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        String spec = "!@#$%^&*()<>{}[]";
        // Reg表达式
        Pattern pattern = Pattern.compile(spec);
        Matcher matcher = pattern.matcher(source.toString());
        // 否有匹配结果
        if (matcher.find()) {
          return "";
        }
        return null;
      }
    }
    

    创建了InputFilter以后,通过EditText的setFilters(InputFilter filters[])方法,注册InputFilter,EditText即可通过InputFilter的规则进行字符控制。setFilters方法传入的是一个InputFilter数组,这意味着你可以创建多个InputFilter,并注册在同一个EditText上。

    // 注册InputFilter
    etText.setFilters({filter1, filter2});
    

    4.keyListener

    InputFilter提供了字符过滤,那么keyListener则提供了对键盘按键的监听。常用的keyListener有两种,一个是NumberKeyListener,用于字符监听;另外一个是DigitsKeyListener用于数字监听。DigitsKeyListener继承NumberKeyListener,而NumberKeyListener实现了InputFilter:

    // 仅接受整数输入
    KeyListener l = new DigitsKeyListener(false, false);
    // 接受有符号的整数输入
    KeyListener l = new DigitsKeyListener(true, false);
    // 接受整数、小数输入
    KeyListener l = new DigitsKeyListener(false, true);
    // 接受有符号的整数、小数输入
    KeyListener l = new DigitsKeyListener(true, true);
    et.setKeyListener(l);
    
    //字符输入过滤
    et.setKeyListener(new NumberKeyListener() {
      @NonNull
      @Override
      protected char[] getAcceptedChars() {
        // 返回可输入字符,相当于android:digits
        return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();;
      }
    
      @Override
      public int getInputType() {
        // 返回输入类型,相当于android:inputType
        return InputType.TYPE_CLASS_TEXT;
      }
    });
    

    可以看出,NumberKeyListener的用法和android:digits属性的使用方法相近。

    5.TextWatcher

    TextWatcher的作用是用于监听输入变化。当EditText设置了TextWatcher监听时,往输入框输入内容时,都会调用TextWatcher的函数。当使用键盘输入时,每输入一个字,就会调用一次TextWatcher的函数;当使用复制粘贴时,每粘贴一次内容,就会调用一次TextWatcher的函数:

    TextWatcher textWatcher = new TextWatcher() {
      @Override
      public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    
      }
    
      @Override
      public void onTextChanged(CharSequence s, int start, int before, int count) {
    
       }
    
      @Override
      public void afterTextChanged(Editable s) {
    
      }
    };
    et.addTextChangedListener(textWatcher);
    

    TextWathcer有三个函数,这里我们一一进行分析:

    1.beforeTextChanged(CharSequence s, int start, int count, int after)

    该函数在输入内容改变之前调用,表示原有文本s,在从start开始count的长度,会被一个长度为after的文本代替。

    2.onTextChanged(CharSequence s, int start, int before, int count)

    该函数在内容改变的过程中调用,表示文本s从start开始到count长度的文本,替换了之前长度为before的文本。该函数调用的时候,文本内容已经被替换。

    3.afterTextChanged(Editable s)

    该函数在内容改变之后调用,其中s表示改变后的内容,可以使用Editable s的方法对文本进行处理。
    对字符过滤,主要在onTextChanged(CharSequence s, int start, int before, int count) 方法中处理,对已经替换的文本内容进行过滤:

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
      String reg = "@#$%^&*()?";
      Pattern pattern = Pattern.compile(reg);
      Matcher match = Pattern.matcher(s.toString());
      // 替换所有特殊字符
      String str = match.replaceAll("").trim();
      et.setText(str); 
    }
    

    5.EditText的InputConnection属性
    此方法参考自博主brycegao321,原理是继承EditText,然后使用inputConnection属性限制字符输入

    public class LimitEditText extends EditText {
        public LimitEditText(Context context) {
            super(context);
        }
    
        public LimitEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public LimitEditText(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        /**
         * 输入法
         * @param outAttrs
         * @return
         */
        @Override
        public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
            return new InnerInputConnecttion(super.onCreateInputConnection(outAttrs),
                    false);
        }
    
        class InnerInputConnecttion extends InputConnectionWrapper implements InputConnection {
    
            public mInputConnecttion(InputConnection target, boolean mutable) {
                super(target, mutable);
            }
    
            /**
             * 对输入的内容进行拦截
             *
             * @param text
             * @param newCursorPosition
             * @return
             */
            @Override
            public boolean commitText(CharSequence text, int newCursorPosition) {
                // 只能输入字母或者数字
                if (!Character.isLetterOrDigit(charSequence.charAt(i)) || isChinese)  {
                    return false;
                }
                return super.commitText(text, newCursorPosition);
            }
    
            @Override
            public boolean sendKeyEvent(KeyEvent event) {
                return super.sendKeyEvent(event);
            }
    
            @Override
            public boolean setSelection(int start, int end) {
                return super.setSelection(start, end);
            }
        }
    }
    

    最后,列出大神写的博客:
    Android EditText实现字符过滤
    Android EditText限制输入字符的5种实现方式
    onTextChanged使用详解

    相关文章

      网友评论

        本文标题:Android EditText 字符过滤

        本文链接:https://www.haomeiwen.com/subject/qessuftx.html