扩展TextWatcher实现监听EditText字数
在Android开发中,有时会需要监听某个EditText中已输入的字数,达到要求后触发某个行为,例如账号或者密码输入框限定最少输入6位英文或数字,达到6位后登录按钮才变为可用。Android提供了一个监听EditText的接口TextWatcher,通过调用EditText里的addTextChangedListener()方法实现监听。TextWatcher里面有三个要实现的方法,我试着根据源码里的注释解释一下三个方法的作用:
public interface TextWatcher extends NoCopySpan {
// 该方法被调用时说明在s中,从下标start开始的count个字符将要被替换为长度为after的字符串
public void beforeTextChanged(CharSequence s, int start, int count, int after);
// 该方法被调用时说明在s中,从start开始的count个字符刚刚替换掉了长度为before的字符串
public void onTextChanged(CharSequence s, int start, int before, int count);
// 该方法被调用时说明在s中的某个地方发生了字符变化
public void afterTextChanged(Editable s);
}
我们要达到的目的是,字符数量满足要求以后执行某操作,字数不够时该操作变为不可执行,因此只需要重写afterTextChanged(Editable s)这个方法就好了。于是我封装了一个抽象类,留出两个抽象方法供使用者实现业务逻辑:
/**
* @author evilyin(ChenZhixi)
* @since 15/10/31
*/
public abstract class TextCountWatcher implements TextWatcher {
//要求的字数
private int count;
public TextCountWatcher(int count) {
this.count = count;
}
@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) {
if (s.length() >= count) {
onTextMatchCount();
}else if (s.length() < count) {
onTextLessThanCount();
}
}
// 当字数达到或超过要求时触发
public abstract void onTextMatchCount();
// 当字数不够时触发
public abstract void onTextLessThanCount();
}
实际使用的例子,mobileNumber是输入手机号的EditText,必须输入11位,才可以点击边上的按钮:
mobileNumber.addTextChangedListener(new TextCountWatcher(11) {
@Override
public void onTextMatchCount() {
canClick();
}
@Override
public void onTextLessThanCount() {
notClick();
}
});
有的时候我们还想实现另一个功能,在某个输入框中输入的字数达到上限后就不能输入了,这同样可以通过TextWatcher实现。下面的代码在参考了网上的写法后自己做了些改进:
/**
* @author evilyin(ChenZhixi)
* @since 15/11/14
*/
public class TextLengthWatcher implements TextWatcher {
private int length; //字数限制
private EditText editText;
private boolean onceLoad = true;
public TextLengthWatcher(int length, EditText editText) {
this.length = length;
this.editText = editText;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int countSize = 0;
Editable editable = editText.getText();
String str = editable.toString();
char[] array = str.toCharArray();
if (onceLoad) {
editText.setSelection(s.length());
onceLoad = false;
}
for (int i = 0; i < array.length; i++) {
if (StringUtil.isChineseChar(str.charAt(i)))/**判断是否为中文*/
{
countSize += 2;/**如果为中文或者中文特殊符号则占两个字节*/
} else {
countSize += 1;/**英文则占一个字节*/
}
if (countSize > length) {
/**达到最大值*/
int selEndIndex = Selection.getSelectionEnd(editable);
str = editable.toString();
String newStr = str.substring(0, i);
editText.setText(newStr);
editable = editText.getText();
int newLen = editable.length();
if (selEndIndex > newLen) {
selEndIndex = editable.length();
}
Selection.setSelection(editable, selEndIndex);
editText.setTextColor(Color.RED);
break;
} else {
editText.setTextColor(Color.BLACK);
}
}
}
@Override
public void afterTextChanged(Editable s) {
}
}
实际使用更方便,不需要实现抽象方法了:
commentEt.addTextChangedListener(new TextLengthWatcher(100, commentEt));
commentEt是评论框EditText,限制字数上限100个字符,在达到上限以后无法输入新的字符,并且字体颜色会变红。
嗯,就这么多了。