简单的Emoji demo

来源:互联网 发布:打字软件有什么 编辑:程序博客网 时间:2024/05/16 11:41

前言:这段时间项目中需要将原来自定义表情更换为emoji表情,而且需要在各平台上都能解析,由于第一版中的表情是我做的,所以这个活又只能由我来折腾了。下面是移植到项目前的demo效果图,使用输入法中的emoji也可以解析。



实现思路:其实跟自定义表情实现基本上是一样的,只过自定义表情中的编码是自己定的,解析的时候使用正则匹配再替换就可以,而emoji要想平台通用,就得使用unicode编码(参考http://code.iamcal.com/php/emoji/),不过本菜鸟对编码这块不了解,差点就对它投降了。现在结合demo解释一下:

第一步:解析emoji(EmojiFileParser.java)

使用pull解析,将节点值转换为emoji的unicode与对应资源id的键值对,存放在SparseIntArray对象中,由于当时写的时候思路比较乱,所以代码不是很整洁,以后会注意的,下面只贴关键代码段,详细的大家可以看demo。

<span style="white-space:pre"></span>/** * @describe TODO 将表情的unicode以键值对的形式添加到集合中  * @param emoji */private void addToMap(EmojiModel emoji) {if(emoji.getUnicode().length() < 6)emojiMap.put(emoji.getUnicode().codePointAt(0), emoji.getResId());}/** * @describe TODO 将表情结点值转换为表情对象  * @param emojiCode xml中解析中节点值 * @return */private EmojiModel convertToEmoji(String emojiCode) {EmojiModel emoji = new EmojiModel();//设置表情的资源idemoji.setResId(context.getResources().getIdentifier("emoji_" + emojiCode,"drawable", context.getPackageName()));if (emojiCode.length() < 6) {//由一个unicode表示的表情<span style="color:#ff0000;">//将xml节点值转换为unicode字符串emoji.setUnicode(new String(Character.toChars(Integer.parseInt(emojiCode, 16))));</span>//只装由一个unicode的表情添加到键值对集合中addToMap(emoji);}else{//由两个unicode表示的表情,解析的时候单独处理,所以不添加到映射集合中String[] emos = emojiCode.split("-");char[] char0 = Character.toChars(Integer.parseInt(emos[0], 16));char[] char1 = Character.toChars(Integer.parseInt(emos[1], 16));char[] unicode = new char[char0.length + char1.length];for (int i = 0; i < char0.length; i++) {unicode[i] = char0[i];}for (int i = char0.length; i < unicode.length; i++) {unicode[i] = char1[i - char0.length];}emoji.setUnicode(new String(unicode));}return emoji;}


第二步:分页显示(EmojiFragment.java)

这点跟自定义表情没有什么区别,网上的demo也很多。

第三步:解析emoji表情(EmojiConvertUtil.java)

解析主要由这个方法完成,

<span style="white-space:pre"></span>/** * @describe TODO 如果传入的字符串中包含表情unicode,则替换为相应的图片 * @param spanStr * @param start 开始的索引位置 * @param length 需要处理的长度 */public void convert(Spannable spanStr, int start, int length){//SpannableString spanStr = new SpannableString(msg);//传入的字符串长度int strLength = spanStr.length();       <span style="white-space:pre"></span>//需要处理的字符串长度,如果没有指定长度,一般都是整个字符串        <span style="white-space:pre"></span>int textLengthToProcessMax = strLength - start;        <span style="white-space:pre"></span>//需要处理的字符串长度,如果指定的超过字符串长度范围,则为整个字符串长度        <span style="white-space:pre"></span>int textLengthToProcess = (length < 0 || length >= textLengthToProcessMax) ? strLength : (length+start);<span style="white-space:pre"></span>int skip = 0;//索引移动的步长,有些字符要由两个char来表示<span style="white-space:pre"></span>int resId = 0;//资源id,等于0表示没有对应的资源<span style="white-space:pre"></span>for(int i=start; i<textLengthToProcess; i+=skip){skip = 0;resId = 0;<span style="color:#ff6666;">int unicode = Character.codePointAt(spanStr, i);skip = Character.charCount(unicode);</span>if (unicode > 0xff) {//unicode不在assic范围内            <span style="white-space:pre"></span>//获取对应资源id               <span style="white-space:pre"></span> <span style="white-space:pre"></span>resId = emojiMap.get(unicode);            <span style="white-space:pre"></span>}<span style="white-space:pre"></span>//当前编码没的找到对应资源且当前位置还有需要处理的字符(主要处理由两个unicode表示的emoji)<span style="white-space:pre"></span>if(resId == 0 && i+skip < textLengthToProcess){<span style="white-space:pre"></span>int followUnicode = Character.codePointAt(spanStr, i + skip);                <span style="white-space:pre"></span>if (followUnicode == 0x20e3) {                    <span style="white-space:pre"></span>int followSkip = Character.charCount(followUnicode);                    <span style="white-space:pre"></span>switch (unicode) {                        case 0x0031:                            resId = R.drawable.emoji_0031_20e3;                            break;                        case 0x0032:                        resId = R.drawable.emoji_0032_20e3;                            break;                        case 0x0033:                        resId = R.drawable.emoji_0033_20e3;                            break;                        case 0x0034:                        resId = R.drawable.emoji_0034_20e3;                            break;                        case 0x0035:                        resId = R.drawable.emoji_0035_20e3;                            break;                        case 0x0036:                        resId = R.drawable.emoji_0036_20e3;                            break;                        case 0x0037:                        resId = R.drawable.emoji_0037_20e3;                            break;                        case 0x0038:                        resId = R.drawable.emoji_0038_20e3;                            break;                        case 0x0039:                        resId = R.drawable.emoji_0039_20e3;                            break;                        case 0x0030:                        resId = R.drawable.emoji_0030_20e3;                            break;                        case 0x0023:                        resId = R.drawable.emoji_0023_20e3;                            break;                        default:                            followSkip = 0;                            break;                    }                    skip += followSkip;               }else {                    int followSkip = Character.charCount(followUnicode);                    switch (unicode) {                        case 0x1f1ef:                            resId = (followUnicode == 0x1f1f5) ? R.drawable.emoji_1f1ef_1f1f5 : 0;                            break;                        case 0x1f1fa:                            resId = (followUnicode == 0x1f1f8) ? R.drawable.emoji_1f1fa_1f1f8 : 0;                            break;                        case 0x1f1eb:                            resId = (followUnicode == 0x1f1f7) ? R.drawable.emoji_1f1eb_1f1f7 : 0;                            break;                        case 0x1f1e9:                            resId = (followUnicode == 0x1f1ea) ? R.drawable.emoji_1f1e9_1f1ea : 0;                            break;                        case 0x1f1ee:                            resId = (followUnicode == 0x1f1f9) ? R.drawable.emoji_1f1ee_1f1f9 : 0;                            break;                        case 0x1f1ec:                            resId = (followUnicode == 0x1f1e7) ? R.drawable.emoji_1f1ec_1f1e7 : 0;                            break;                        case 0x1f1ea:                            resId = (followUnicode == 0x1f1f8) ? R.drawable.emoji_1f1ea_1f1f8 : 0;                            break;                        case 0x1f1f7:                            resId = (followUnicode == 0x1f1fa) ? R.drawable.emoji_1f1f7_1f1fa : 0;                            break;                        case 0x1f1e8:                            resId = (followUnicode == 0x1f1f3) ? R.drawable.emoji_1f1e8_1f1f3 : 0;                            break;                        case 0x1f1f0:                            resId = (followUnicode == 0x1f1f7) ? R.drawable.emoji_1f1f0_1f1f7 : 0;                            break;                        default:                            followSkip = 0;                            break;                    }                    skip += followSkip;                }}<span style="white-space:pre"></span>if(resId != 0){spanStr.setSpan(getImageSpan(resId), i, i+skip, <span style="white-space:pre"></span>Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>}<span style="white-space:pre"></span>}

在EditText中要解析系统键盘的emoji,则需要重写一下EditText(EmojiEditText.java).

@Overrideprotected void onTextChanged(CharSequence text, int start,int lengthBefore, int lengthAfter) {//将后添加的字符串进行处理EmojiConvertUtil.getInstance(getContext()).convert(getText(), start, lengthAfter);}
</pre><pre name="code" class="java"><strong>结语</strong>:demo中对所有的表情都进行了解析并分了类,只是自己项目中只需要用到其中的一些,所以没有全部显示,另外有些特殊的表情(由两个unicode表示的emoji),本菜鸟并没有做测试,所以大家需要留意。下载地址:<a target=_blank href="http://download.csdn.net/detail/ihuaren/8212245">点击打开链接</a><span style="font-family: Arial, Helvetica, sans-serif;">(上传时一直提示在百分之九十九就不动了,不知道可不可以用)</span>
<span style="font-family: Arial, Helvetica, sans-serif;"></span>
</pre><pre name="code" class="java"><strong>参考资料:</strong>
1、https://github.com/rockerhieu/emojicon
2、http://www.cnblogs.com/stay/archive/2012/10/30/2746489.html

0 0