说明
自定义Editext文本监听textWatcher,限制字符数量
- String.length()误区
- byte编码不同,汉字和字母的比率也不同
- 不同字符长度如何区分截取
- 光标的处理
String.length()误区
因为我们是监听Editext字符数量,那么问题来了,String.length()方法能否直接判断长度,答案是否定的,我们的输入框既可以输入汉字,也可以输入英文字母,或者也可以输入数字,他们在不同的字节编码下,对应的长度关系也截然不同,所以只能采取byte数组来判断
不同字符集编码,对应的长度关系
英文字母:
字节数 : 1;编码:GB2312
字节数 : 1;编码:GBK
字节数 : 1;编码:GB18030
字节数 : 1;编码:ISO-8859-1
字节数 : 1;编码:UTF-8
字节数 : 4;编码:UTF-16
字节数 : 2;编码:UTF-16BE
字节数 : 2;编码:UTF-16LE
中文汉字:
字节数 : 2;编码:GB2312
字节数 : 2;编码:GBK
字节数 : 2;编码:GB18030
字节数 : 1;编码:ISO-8859-1
字节数 : 3;编码:UTF-8
字节数 : 4;编码:UTF-16
字节数 : 2;编码:UTF-16BE
字节数 : 2;编码:UTF-16LE
不同的字符长度如何截取
比如,我们的限定字符长度为20,现在已经输入了19个字符,如果在输入两个字母,那么就变成21个字符,直接截取掉最后一个即可,但是如果此时输入一个汉字,如何截取,一个汉字占用2个字符,总不能把汉字截去一半吧,那么有可能出现乱码,此时直接舍去汉字。
光标的处理
监听文本光标一定要放到后面,不然也会有各种问题
代码
public class CustomWatcherText implements TextWatcher {
private int maxLen = 10; //默认长度为10个字符
private EditText editText = null;
private Context context;
public CustomWatcherText(Context context, int maxLen, EditText editText) {
this.maxLen = maxLen;
this.editText = editText;
this.context = context;
}
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
try {
// TODO Auto-generated method stub
Editable editable = editText.getText();
String content = editText.getText().toString();
byte[] bt = content.getBytes("gb2312");
if (bt.length > maxLen) {
int selEndIndex = Selection.getSelectionEnd(editable);
String str = editable.toString();
byte[] bt2 = str.getBytes("gb2312");
byte[] bt3 = subBytes(bt2, 0, maxLen);
String newStrs = gbToString(bt3);
String temp = String.valueOf(newStrs.charAt(newStrs.length() - 1));
boolean flag = isContainChinese(temp);
boolean flag2 = isContainLetters(temp);
if (!flag && !flag2) {
String newStrs2 = newStrs.substring(0, newStrs.length() - 1);
editText.setText(newStrs2);
} else {
editText.setText(newStrs);
}
editable = editText.getText();
// 新字符串的长度
int newLen = editable.length();
// 旧光标位置超过字符串长度
if (selEndIndex >= newLen) {
selEndIndex = editable.length();
}
//设置新光标所在的位置
Selection.setSelection(editable, selEndIndex);
Toast.makeText(context,"超出"+maxLen/2+"个汉字",Toast.LENGTH_SHORT).show();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
private byte[] subBytes(byte[] src, int begin, int count) {
byte[] bs = new byte[count];
System.arraycopy(src, begin, bs, 0, count);
return bs;
}
private String gbToString(byte[] data) {
String str = null;
try {
str = new String(data, "gb2312");
} catch (UnsupportedEncodingException e) {
}
return str;
}
/**
* 判断字符串是否包含字母
* @param str
* @return
*/
public boolean isContainLetters(String str) {
for (char i = 'A'; i <= 'Z'; i++) {
if (str.contains(String.valueOf(i))) {
return true;
}
}
for (char i = 'a'; i <= 'z'; i++) {
if (str.contains(String.valueOf(i))) {
return true;
}
}
return false;
}
/**
* 判断字符串是否包含中文
* @param str
* @return
*/
public boolean isContainChinese(String str) {
Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
Matcher m = p.matcher(str);
return m.find();
}
}
在Editext监听的地方使用:
editext.addTextChangedListener(new CustomWatcherText(context, 20, editext));
非常感谢你的浏览!