public class EmojiEditText extends EditText {
// 输入表情前的光标位置
private int cursorPos; // 输入表情前EditText中的文本
private String inputAfterText; // 是否重置了EditText的内容
private boolean resetText;
private Context mContext;

public EmojiEditText(Context context) {
super(context);
this.mContext = context;
initEditText();
}

public EmojiEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
initEditText();
}

public EmojiEditText(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
initEditText();
} // 初始化edittext 控件

private void initEditText() {
addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start,
int before, int count) {
if (!resetText) {
cursorPos = 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
CharSequence input = s.subSequence(cursorPos, cursorPos
+ count);
if (containsEmoji(input.toString())) {
resetText = true;
//暂不支持输入Emoji表情符号
Toast.makeText(mContext, "暂不支持输入表情符号",
Toast.LENGTH_SHORT).show(); // 是表情符号就将文本还原为输入表情符号之前的内容
setText(inputAfterText);
CharSequence text = 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 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));
}

}

最新文章

  1. MySQL数据表range分区例子
  2. AJAX原理及应用
  3. java识别验证码
  4. 5.1.1 读取Redis 数据
  5. nginx+lua+redis高并发应用建设
  6. octet-stream
  7. eclipse的插件开发-启动时间
  8. MySQL通过localhost无法连接数据库的解决
  9. python小练习: 给定一个数组 按重复次数 降序排列输出 数组非空且为正整数
  10. django分页
  11. Spring Boot实现文件下载功能
  12. 关于Socket.IO的知识点记录
  13. 560. Subarray Sum Equals K 求和为k的子数组个数
  14. WD与循环 组合数学
  15. appium自动化测试之元素定位
  16. python-装饰器模式
  17. Android Volley 库的使用
  18. 解决vuejs应用在nginx非根目录下部署时访问404的问题
  19. Python查询数据库时候遇到的乱码问题
  20. 2.7 The Object Model -- Bindings, Observers, Computed Properties:What do I use when?

热门文章

  1. JSP(3) - 9个JSP内置对象 - 小易Java笔记
  2. Redis -- 数据类型小结
  3. linux命令(12):ping命令
  4. Django如何使文件在django自动执行
  5. Android点击图标重新启动问题
  6. 通过IP地址和子网掩码计算主机数
  7. thinkphp之url的seo优化
  8. Poj2182 Lost Cows(玄学算法)
  9. SCU - 4439 Vertex Cover (图的最小点覆盖集)
  10. 【BZOJ 2151】 2151: 种树 (贪心+堆+双向链表)