前言:最後客戶反饋過來一個問題說是在華爲mate7 和 魅族手機上出現在26鍵編輯模式下程序會崩潰,我在公司用的是小米的測試機,所有就從來都沒有遇到這樣的情況.我的小米的手機的輸入情況如下圖,這樣的情況是不會報錯的.但是華爲的手機和魅族的手機會在輸入框中也顯示你正在輸入的內容就導致我在使用表情過濾的監聽裏面會出現獲取到的字符串的數量出現偏差.
我的表情過濾工具類是這樣寫的
/**
* 輸入幫助類
*/
public class EditTextHelper {
/**
* 設置EditText內容並移動光標到尾部
*
* @param edittext
* @param text
*/
public static void setTextAndSelectEnd(EditText edittext, CharSequence text) {
edittext.setText(text);
edittext.setSelection(edittext.getText().length());
}
public static void addEmojiFilter(final EditText edittext) {
edittext.addTextChangedListener(new TextWatcher() {
// 是否重置了EditText的內容
private boolean resetText;
private int cursorPos;
// 輸入表情前EditText中的文本
private String inputAfterText;
@Override
public void beforeTextChanged(CharSequence s, int start,
int before, int count) {
if (!resetText) {
cursorPos = edittext.getSelectionEnd();
// 這裏用s.toString()而不直接用s是因爲如果用s,
// 那麼,inputAfterText和s在內存中指向的是同一個地址,s改變了,
// inputAfterText也就改變了,那麼表情過濾就失敗了
inputAfterText = s.toString();
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (!resetText) {
if (count >= 2) {// 表情符號的字符長度最小爲2
//如果這裏不加這樣的判斷就會應該剛剛之前的操作報下標越界的錯誤
// if (cursorPos + count > s.length()) {
// return;
// }
CharSequence input = s.subSequence(cursorPos, cursorPos + count);
if (containsEmoji(input.toString())) {
resetText = true;
// Toast.makeText(mContext, "不支持輸入Emoji表情符號",
// Toast.LENGTH_SHORT).show();
// 是表情符號就將文本還原爲輸入表情符號之前的內容
inputAfterText += filterEmoji(input.toString());
edittext.setText(inputAfterText);
CharSequence text = edittext.getText();
if (text instanceof Spannable) {
Spannable spanText = (Spannable) text;
Selection.setSelection(spanText, text.length());
}
}
}
} else {
resetText = false;
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
/**
* 檢測是否有emoji表情
*
* @param source
* @return
*/
public static boolean containsEmoji(String source) {
int len = source.length();
for (int i = 0; i < len; i++) {
char codePoint = source.charAt(i);
if (!isEmojiCharacter(codePoint)) { // 如果不能匹配,則該字符是Emoji表情
return true;
}
}
return false;
}
/**
* 過濾emoji表情
*
* @param source
* @return
*/
public static String filterEmoji(String source) {
StringBuilder sb = new StringBuilder();
int len = source.length();
for (int i = 0; i < len; i++) {
char codePoint = source.charAt(i);
if (isEmojiCharacter(codePoint)) { // 如果不能匹配,則該字符是Emoji表情
// return true;
sb.append(codePoint);
}
}
return sb.toString();
}
/**
* 判斷是否是Emoji
*
* @param codePoint 比較的單個字符
* @return
*/
private static boolean isEmojiCharacter(char codePoint) {
return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
|| (codePoint == 0xD)
|| ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
|| ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
|| ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
}
/**
* 銀行卡四位加空格
*
* @param mEditText
*/
public static void bankCardNumAddSpace(final EditText mEditText) {
mEditText.addTextChangedListener(new TextWatcher() {
int beforeTextLength = 0;
int onTextLength = 0;
boolean isChanged = false;
int location = 0;// 記錄光標的位置
private char[] tempChar;
private StringBuffer buffer = new StringBuffer();
int konggeNumberB = 0;
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
beforeTextLength = s.length();
if (buffer.length() > 0) {
buffer.delete(0, buffer.length());
}
konggeNumberB = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') {
konggeNumberB++;
}
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
onTextLength = s.length();
buffer.append(s.toString());
if (onTextLength == beforeTextLength || onTextLength <= 3
|| isChanged) {
isChanged = false;
return;
}
isChanged = true;
}
@Override
public void afterTextChanged(Editable s) {
if (isChanged) {
location = mEditText.getSelectionEnd();
int index = 0;
while (index < buffer.length()) {
if (buffer.charAt(index) == ' ') {
buffer.deleteCharAt(index);
} else {
index++;
}
}
index = 0;
int konggeNumberC = 0;
while (index < buffer.length()) {
if ((index == 4 || index == 9 || index == 14 || index == 19)) {
buffer.insert(index, ' ');
konggeNumberC++;
}
index++;
}
if (konggeNumberC > konggeNumberB) {
location += (konggeNumberC - konggeNumberB);
}
tempChar = new char[buffer.length()];
buffer.getChars(0, buffer.length(), tempChar, 0);
String str = buffer.toString();
if (location > str.length()) {
location = str.length();
} else if (location < 0) {
location = 0;
}
mEditText.setText(str);
Editable etable = mEditText.getText();
Selection.setSelection(etable, location);
isChanged = false;
}
}
});
}
/**
* 輸入框字數顯示
* @param editText 輸入框
* @param tvShow 字數顯示控件
* @param maxNumber 最大值
*/
public static void editContentNumber(final EditText editText,final TextView tvShow,final int maxNumber){
// editText. setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxNumber) });
editText.addTextChangedListener(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) {
tvShow.setText(String.format("%d/%d",editText.getText().length(),maxNumber));
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
}
*加一層這樣的判斷,就可以避免這種現象發生
if (cursorPos + count > s.length()) {
return;
}
- 另外如果公司如果有需要過濾到表情的話,這個工具類挺好用的,只需要再activity或者是fragment的oncreat方法裏面 初始化一次就可以了 例如
EditTextHelper.addEmojiFilter(editext);//過濾掉表情 不讓用戶輸入表情