简单的Emoji demo

前言:这段时间项目中需要将原来自定义表情更换为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();
		
		//设置表情的资源id
		emoji.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).

	@Override
	protected 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值