說明
自定義Editext文本監(jiān)聽textWatcher,限制字符數(shù)量
- String.length()誤區(qū)
- byte編碼不同,漢字和字母的比率也不同
- 不同字符長度如何區(qū)分截取
- 光標(biāo)的處理
String.length()誤區(qū)
因為我們是監(jiān)聽Editext字符數(shù)量,那么問題來了,String.length()方法能否直接判斷長度,答案是否定的,我們的輸入框既可以輸入漢字,也可以輸入英文字母,或者也可以輸入數(shù)字,他們在不同的字節(jié)編碼下,對應(yīng)的長度關(guān)系也截然不同,所以只能采取byte數(shù)組來判斷
不同字符集編碼,對應(yīng)的長度關(guān)系
英文字母:
字節(jié)數(shù) : 1;編碼:GB2312
字節(jié)數(shù) : 1;編碼:GBK
字節(jié)數(shù) : 1;編碼:GB18030
字節(jié)數(shù) : 1;編碼:ISO-8859-1
字節(jié)數(shù) : 1;編碼:UTF-8
字節(jié)數(shù) : 4;編碼:UTF-16
字節(jié)數(shù) : 2;編碼:UTF-16BE
字節(jié)數(shù) : 2;編碼:UTF-16LE
中文漢字:
字節(jié)數(shù) : 2;編碼:GB2312
字節(jié)數(shù) : 2;編碼:GBK
字節(jié)數(shù) : 2;編碼:GB18030
字節(jié)數(shù) : 1;編碼:ISO-8859-1
字節(jié)數(shù) : 3;編碼:UTF-8
字節(jié)數(shù) : 4;編碼:UTF-16
字節(jié)數(shù) : 2;編碼:UTF-16BE
字節(jié)數(shù) : 2;編碼:UTF-16LE
不同的字符長度如何截取
比如,我們的限定字符長度為20,現(xiàn)在已經(jīng)輸入了19個字符,如果在輸入兩個字母,那么就變成21個字符,直接截取掉最后一個即可,但是如果此時輸入一個漢字,如何截取,一個漢字占用2個字符,總不能把漢字截去一半吧,那么有可能出現(xiàn)亂碼,此時直接舍去漢字。
光標(biāo)的處理
監(jiān)聽文本光標(biāo)一定要放到后面,不然也會有各種問題
代碼
public class CustomWatcherText implements TextWatcher {
private int maxLen = 10; //默認(rèn)長度為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();
// 舊光標(biāo)位置超過字符串長度
if (selEndIndex >= newLen) {
selEndIndex = editable.length();
}
//設(shè)置新光標(biāo)所在的位置
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監(jiān)聽的地方使用:
editext.addTextChangedListener(new CustomWatcherText(context, 20, editext));
非常感謝你的瀏覽!