前言:最后客户反馈过来一个问题说是在华为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);//过滤掉表情 不让用户输入表情