Android EditText 字符过滤

我们使用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使用详解

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容