之前有過(guò)一段時(shí)間,安卓輸入框中禁止輸入中文的實(shí)現(xiàn)方式是自定義一個(gè)TextWatcher耳标,然后在afterTextChanged中判斷是否輸入的是中文邑跪,如果是中文則再做撤銷回滾操作呼猪,也就是做刪掉輸入中文的處理砸琅。不過(guò)感覺(jué)只是為了處理這一個(gè)邏輯就要寫那么多臃腫的代碼,簡(jiǎn)潔性以及可閱讀性不好谚赎,后來(lái)想到了使用InputFilter過(guò)濾的方式诱篷,大大簡(jiǎn)化了代碼,并將該方法公布到工具類當(dāng)中便于其他地方復(fù)用闸盔。
1琳省、使用方法
public static void filterChinese(TextView v) {
v.setFilters(new InputFilter[]{new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (null != source && isChinese(source.toString())) return "";
return source;
}
}});
}
// 完整的判斷中文漢字和符號(hào)
@SuppressWarnings("unused")
private static boolean isChinese(String strName) {
char[] ch = strName.toCharArray();
for (char c : ch) {
if (isChinese(c)) {
return true;
}
}
return false;
}
// 根據(jù)Unicode編碼完美的判斷中文漢字和符號(hào)
private static boolean isChinese(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION;
}
這里思想很簡(jiǎn)單针贬,也就是在輸入過(guò)程中直接過(guò)濾掉中文。
2荡灾、原理解析
對(duì)于想繼續(xù)知道該過(guò)濾原理的同學(xué)瞬铸,這里我直接上一些源碼片段。
這里上下TextView的setFilters方法源碼:
public void setFilters(InputFilter[] filters) {
if (filters == null) {
throw new IllegalArgumentException();
}
mFilters = filters;
if (mText instanceof Editable) {
setFilters((Editable) mText, filters);
}
}
可以看出荧缘,實(shí)際上操作InputFilter的地方應(yīng)該有兩處拦宣,一處是TextView本身,還有一處是Editable绸罗。
- 首先看下TextView處理的源碼
private void setText(CharSequence text, BufferType type, boolean notifyBefore, int oldlen) {
......
int n = mFilters.length;
for (int i = 0; i < n; i++) {
CharSequence out = mFilters[i].filter(text, 0, text.length(), EMPTY_SPANNED, 0, 0);
if (out != null) {
text = out;
}
}
......
}
代碼很簡(jiǎn)單豆瘫,就是在執(zhí)行了setText時(shí)再執(zhí)行mFilters數(shù)組外驱,從中獲取過(guò)濾掉之后的內(nèi)容腻窒。
- 然后再分析下Editable
Editable實(shí)際上只是一個(gè)接口磅崭,這里可以想到的實(shí)際上實(shí)現(xiàn)該接口的是SpannableStringBuilder類,參見(jiàn)實(shí)現(xiàn):
public class SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable, Appendable, GraphicsOperations
SpannableStringBuilder類主要作用是修改部分字體樣式柔逼,背景顏色等等恩够,這里不做贅述。處理InputFilter的源碼如下:
public SpannableStringBuilder replace(final int start, final int end, CharSequence tb, int tbstart, int tbend) {
checkRange("replace", start, end);
int filtercount = mFilters.length;
for (int i = 0; i < filtercount; i++) {
CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end);
if (repl != null) {
tb = repl;
tbstart = 0;
tbend = repl.length();
}
}
}
可以看出其當(dāng)執(zhí)行內(nèi)容樣式替換過(guò)程中過(guò)濾掉需要過(guò)濾的內(nèi)容儡毕。
好了扑媚,本篇內(nèi)容到此結(jié)束,如果有用到該方法的地方费坊,拿走不謝旬痹。