应用需要用到聊天功能,考虑到开始需求不大,暂时先用第三方的。
一研究发现界面风格有点不符合整体的风格,加上需要一些自己的特定的需求和界面显示,于是就决定调用第三方数据接口,界面自己写。功能只需要文字,表情和语音就ok,我选择先做表情的。
表情一般都是用 [] 或者类似这种 "/:^_^", "/:^$^", "/:Q" 方式表示,我们用到的就是后者。解析消息类似于: /:^_^你好,abc。
基本思路就是:找到每个/:开头的,然后截取后面的N位,放到表情数组去匹配,然后继续下一个,直到末尾。接着统计了表情数组,记录了总共有哪些长度的表情字符,还按统计的数目对长度排了个序,出现次数多的长度排在前面。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public CharSequence initMessageRecord(String content){ SpannableStringBuilder ssb = new SpannableStringBuilder(content); int[] smileLen = IMSmilyCache.getLenIndex(); int contentLen = content.length(); int index = 0; String tempContent = content; while (index < contentLen) { content = tempContent.substring(index); int nextIndex = content.indexOf("/:", 1); String tmpStr; if (nextIndex >= 0) { tmpStr = content.substring(0, nextIndex); } else { tmpStr = content; } int resId = IMSmilyCache.getInstance().getSimpleShortCutDrawable(tmpStr); if (resId != -1) { initFace(ssb, resId, index,index + tmpStr.length()); } else { //截取的字符串没直接匹配到表情 String tmpTarget; for (int tmpLen : smileLen) { if (tmpStr.length() < tmpLen) continue; tmpTarget = tmpStr.substring(0, tmpLen); resId = IMSmilyCache.getInstance().getSimpleShortCutDrawable(tmpTarget); if (resId != -1) { initFace(ssb, resId, index, index + tmpTarget.length()); tmpStr = tmpTarget; break; } } } index += tmpStr.length(); } return ssb; } private void initFace(SpannableStringBuilder ssb, int resId, int start, int end) { Drawable d = activity.getResources().getDrawable(resId); d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE); ssb.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class IMSmilyCache { 2 private static String[] meanings = {"微笑", "害羞", "吐舌头", "偷笑", "爱幕", "大笑", "跳舞", "飞吻", "安慰", "抱抱", "加油", "胜利", "强", "亲亲", "花痴", "露齿笑", "查找", "呼叫", "算账", "财迷", "好主意", "鬼脸", "天使", "再见", "流口水", "享受", "色情狂", "呆若木鸡", "思考", "迷惑", "疑问", "没钱了", "无聊", "怀疑", "嘘", "小样", "摇头", "感冒", "尴尬", "傻笑", "不会吧", "无奈", "流汗", "凄凉", "困了", "晕", "忧伤", "委屈", "悲泣", "大哭", "痛哭", "I服了U", "对不起", "再见", "皱眉", "好累", "生病", "吐", "背", "惊讶", "惊愕", "闭嘴", "欠扁", "鄙视你", "大怒", "生气", "财神", "学习雷锋", "恭喜发财", "小二", "老大", "邪恶", "单挑", "CS", "隐形人", "炸弹", "惊声尖叫", "漂亮MM", "帅哥", "招财猫", "成交", "鼓掌", "握手", "红唇", "玫瑰", "残花", "爱心", "心碎", "钱", "财物", "礼物", "收邮件", "电话", "举杯庆祝", "时钟", "等待", "很晚了", "飞机", "支付宝"}; 3 private static IMSmilyCache mSmilyCache = new IMSmilyCache(); 4 private static int[] lenIndex; 5 6 /** 7 * 此处优化表情查找速度,按出现次数的概率从大到小排序 8 */ 9 static { 10 HashMap<Integer, Integer> map = new HashMap<>(); 11 int[] len = new int[20]; 12 for (int i = 0; i < shortCuts.length; i++) { 13 int cutsLen = shortCuts[i].length(); 14 len[cutsLen]++; 15 } 16 17 for (int i = 0; i < len.length; i++) { 18 if (len[i] != 0) { 19 map.put(len[i], i); 20 } 21 } 22 23 SortUtil sortUtil = new SortUtil(); 24 sortUtil.sort(len); 25 26 int size = 0; 27 for (int i = 0; i < len.length; i++) { 28 if (len[i] == 0) { 29 size = i; 30 break; 31 } 32 } 33 lenIndex = new int[size]; 34 for (int i = 0; i < size; i++) { 35 lenIndex[i] = map.get(len[i]); 36 } 37 38 LogUtils.fff(""+ Arrays.toString(lenIndex)); 39 } 40 41 public static void main(String[] args) { 42 System.out.println(shortCuts.length); 43 System.out.println(meanings.length); 44 } 45 46 public static IMSmilyCache getInstance() { 47 return mSmilyCache; 48 } 49 50 public String[] getShortCuts() { 51 return shortCuts; 52 } 53 54 public int getSimpleShortCutDrawable(String context){ 55 for (int i = 0; i < shortCuts.length; i++) { 56 if (context.equals(shortCuts[i])) { 57 return smileResArray[i]; 58 } 59 } 60 if (context.equals("shanchu")) { 61 return R.drawable.aliwx_shanchu_dw; 62 } 63 return -1; 64 } 65 66 public static int[] getLenIndex() { 67 return lenIndex; 68 } 69 }
===============
关于删除表情的操作,在使用过程用发现,使用系统自带的键盘能够正确的删除整个表情,于是删除按钮事件就只有两行代码
KeyEvent keyEventDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL);
editText.onKeyDown(KeyEvent.KEYCODE_DEL, keyEventDown);