我们使用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使用详解
网友评论