Android表情文字EmotionText解析
来源:互联网 发布:沙盘类似软件 编辑:程序博客网 时间:2024/04/30 08:16
现在几乎所有的聊天类App都支持输入表情混合文字,但是Android的EditText通常只能输入文字。
今天就来实现一个可以显示表情混合文字的EditText和TextView。
老规矩,在节目开始之前,先来一个搞笑段子:
“大师,我有目标,有远见,心胸开阔,但为什么生活总不如意?”
大师把我带到一棵梅花树前。看着那暗暗吐露芬芳的梅花,我大有所悟。
“大师,你是要告诉我梅花香自苦寒来,只要坚持就能成功?”
“傻逼,梅前你说个屁啊!”
先来看一下实现的效果图
整体功能就两个:可以在EditText中输入表情和文字,接收到表情和文字混合的消息可以显示在TextView中。
先不看代码,先说一下原理,把原理弄明白了,再看代码就很清晰。
在这个工程中,使用的就是系统的EditText和TextView,所以可以看出来显示表情并不是我自定义的功能,而是本身就支持的。只不过通常EditText和TextView在显示文本时,我们输入的都是普通的String或者Charsequence,要显示表情,就不能输入普通的String了,而是输入一个特殊的东西,叫SpannableString。
SpannableString,从名字也能看出来,它就是String字符串,只不过它在显示的时候,会把字符串中的一部分替换成一张图片,而当你调用editText.getText()方法时,返回的还是String字符串。所以它就是一段字符串和一张图片的对应。在显示的时候是图片,getText()取出时是String。
这个原理解释清楚后,示例图所展示的功能就不难了。
首先是输入:
每点击一个表情,就构建一个SpannableString对象,这个SpannableString对象就是一个String和一张表情图片的对应,然后设置给EditText,EditText显示成表情图片;点击发送,取出EditText的内容,返回的就是String,然后把String发送出去,对方接受到String后,找到SpannableString对象中和表情图片对应的String,重新构建SpannableString对象,再显示在TextView中。
绕来绕去,就是String和表情图片的转来转去。
下面来讲代码实现:
1)、找24张表情图片,我就是从QQ中拿来的。
2)、在assets中新建emotions.xml文件
<emotions> <emotion> <code><![CDATA[[em:1:]]]></code> <name>f001</name> </emotion> <emotion> <code><![CDATA[[em:2:]]]></code> <name>f002</name> </emotion> <emotion> <code><![CDATA[[em:3:]]]></code> <name>f003</name> </emotion> <emotion> <code><![CDATA[[em:4:]]]></code> <name>f004</name> </emotion> <emotion> <code><![CDATA[[em:5:]]]></code> <name>f005</name> </emotion> <emotion> <code><![CDATA[[em:6:]]]></code> <name>f006</name> </emotion> <emotion> <code><![CDATA[[em:7:]]]></code> <name>f007</name> </emotion> <emotion> <code><![CDATA[[em:8:]]]></code> <name>f008</name> </emotion> <emotion> <code><![CDATA[[em:9:]]]></code> <name>f009</name> </emotion> <emotion> <code><![CDATA[[em:10:]]]></code> <name>f010</name> </emotion> <emotion> <code><![CDATA[[em:11:]]]></code> <name>f011</name> </emotion> <emotion> <code><![CDATA[[em:12:]]]></code> <name>f012</name> </emotion> <emotion> <code><![CDATA[[em:13:]]]></code> <name>f013</name> </emotion> <emotion> <code><![CDATA[[em:14:]]]></code> <name>f014</name> </emotion> <emotion> <code><![CDATA[[em:15:]]]></code> <name>f015</name> </emotion> <emotion> <code><![CDATA[[em:16:]]]></code> <name>f016</name> </emotion> <emotion> <code><![CDATA[[em:17:]]]></code> <name>f017</name> </emotion> <emotion> <code><![CDATA[[em:18:]]]></code> <name>f018</name> </emotion> <emotion> <code><![CDATA[[em:19:]]]></code> <name>f019</name> </emotion> <emotion> <code><![CDATA[[em:20:]]]></code> <name>f020</name> </emotion> <emotion> <code><![CDATA[[em:21:]]]></code> <name>f021</name> </emotion> <emotion> <code><![CDATA[[em:22:]]]></code> <name>f022</name> </emotion> <emotion> <code><![CDATA[[em:23:]]]></code> <name>f023</name> </emotion> <emotion> <code><![CDATA[[em:24:]]]></code> <name>f024</name> </emotion></emotions>
这里就是24个表情对应的String,这个保存在assets中,相当于一个配置文件。最红要用Java对象来保存这些。
3)、新建Java Bean:Emotion
public class Emotion { private String code = null; private String name = null; public Emotion() {} public Emotion(String code, String name) { this.code = code; this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
4)、解析emotions.xml文件,保存成List
public static List<Emotion> getEmotions(InputStream inputStream) { XmlPullParser parser = Xml.newPullParser(); int eventType = 0; List<Emotion> emotions = null; Emotion emotion = null; try { parser.setInput(inputStream, "UTF-8"); eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_DOCUMENT: emotions = new ArrayList<Emotion>(); break; case XmlPullParser.START_TAG: if ("emotion".equals(parser.getName())) { emotion = new Emotion(); } else if ("code".equals(parser.getName())) { emotion.setCode(parser.nextText()); } else if ("name".equals(parser.getName())) { emotion.setName(parser.nextText()); } break; case XmlPullParser.END_TAG: if ("emotion".equals(parser.getName())) { emotions.add(emotion); emotion = null; } break; default: break; } eventType = parser.next(); } } catch (Exception e) { e.printStackTrace(); } return emotions; }
这个就是常规的xml解析,无所谓用哪种解析方法,反正返回正确就行。
5)、用GridView展示所有的表情
ArrayList<HashMap<String, Object>> items = getItems();SimpleAdapter saImageItems = new SimpleAdapter(this, items, R.layout.emotion_item, new String[] { "itemImage" }, new int[] { R.id.iv_emotion });gvEmotions.setAdapter(saImageItems);
6)、点击表情时,构建SpannableString显示在EditText中(重点)
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Emotion emotion = emotions.get(position); int cursor = etInput.getSelectionStart(); Field f; try { f = (Field) R.drawable.class.getDeclaredField(emotion.getName()); int j = f.getInt(R.drawable.class); Drawable d = getResources().getDrawable(j); int textSize = (int)etInput.getTextSize(); d.setBounds(0, 0, textSize, textSize); String str = null; int pos = position + 1; if (pos < 10) { str = "f00" + pos; } else if (pos < 100) { str = "f0" + pos; } else { str = "f" + pos; } SpannableString ss = new SpannableString(str); ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BOTTOM); ss.setSpan(span, 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); etInput.getText().insert(cursor, ss); } catch (Exception e) { e.printStackTrace(); }}
这步是关键,首先根据点击的位置获取Emotion,然后根据name,用反射获取Drawable。
然后用Drawable创建ImageSpan,把ImageSpan设置给SpannableString。
最后调用editText.getText().insert(cursor, ss);设置显示内容。
详细解释:
24个表情是用f001-f024表示的,对应的24个图片名字也是f001.png-f024.png
根据我点击的位置,构建出具体的str和drawable。
str用来创建SpannableString。
SpannableString ss = new SpannableString(str);
drawable用来创建ImageSpan。
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BOTTOM);
那这两个是怎么关联的呢?就是下一行代码:
ss.setSpan(span, 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
用span来对应ss中从0到str.length()这段字符串。
最后调用显示
editText.getText().insert(cursor, ss);
整个过程就是这样。
7)接受到表情文字混合的消息,显示在TextView中
String receiveString = receiveMessage();SpannableString spannableString = ExpressionUtil.getExpressionString(receiveString );textView.setText(spannableString );
就三部,关键是第二部getExpressionString方法是怎么实现的。
public static final String PATTEN_STR = "f0[0-9]{2}|f10[0-7]";public static SpannableString getExpressionString(Context context, String str, int textSize) { SpannableString spannableString = new SpannableString(str); Pattern sinaPatten = Pattern.compile(PATTEN_STR, Pattern.CASE_INSENSITIVE); try { dealExpression(context, spannableString, textSize, sinaPatten, 0); } catch (Exception e) { Log.e("dealExpression", e.getMessage()); } return spannableString;}public static void dealExpression(Context context, SpannableString spannableString, int textSize, Pattern patten, int start) throws Exception { Matcher matcher = patten.matcher(spannableString); while (matcher.find()) { String key = matcher.group(); if (matcher.start() < start) { continue; } Field field = R.drawable.class.getDeclaredField(key); int resId = field.getInt(R.drawable.class); if (resId != 0) { Drawable d = context.getResources().getDrawable(resId); d.setBounds(0, 0, textSize, textSize); ImageSpan imageSpan = new ImageSpan(d); int end = matcher.start() + key.length(); spannableString.setSpan(imageSpan, matcher.start(), end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); if (end < spannableString.length()) { dealExpression(context, spannableString, textSize, patten, end); } break; } }}
我们所有的表情都是用f001-f024来对应的,所以,接受到消息String后,就要找出String中所有匹配f001-f024这种格式的,然后替换成对应的表情图片。
所以这段代码看似很多,其实就是对接受到的String,用正则表达式进行遍历匹配,每匹配到一个,就把匹配到的那一段用一个ImageSpan来对应,直到全部匹配完。
最后把最终的SpnanableString设置给TextView。
大工告成!!!
至此,整个实现的逻辑就讲完了,但是我的工程中远不止这些,还有很多边缘性的功能,但核心的东西都讲了。
最后,我把完整的工程代码放出来,需要的朋友下载吧。
http://download.csdn.net/detail/u011002668/9462085
本期节目就到这里,感谢大家的收看,下期再见。
(PS:最初写博客就是为了记录自己学习的知识点,但既然写了,还是想写好点,或许对别人能起到帮助的作用,本人水平有限,如果有不对的地方,欢迎指正。)
- Android表情文字EmotionText解析
- Android---文字中插入表情
- Android---文字中插入表情
- Android---文字中插入表情
- Android---文字中插入表情
- android textview 显示表情和文字 表情带超链接
- Android解析qq聊天记录表情
- android中文字高亮+表情
- 表情解析
- Android开发(16)-TextView显示表情图像和文字
- Android开发(16)-TextView显示表情图像和文字
- Android开发(16)-TextView显示表情图像和文字
- Android开发之SpannableString详解(表情文字)
- Android开发 TextView显示表情图像和文字
- android编辑框禁用emoji表情和颜文字
- 表情,文字 图文混编
- php文字替换表情
- android 表情的输入 Unicode实现表情展示 无需图片素材及相关解析
- RDK中的Vps_printf()与Vps_rprintf()
- android中 页面间的无阻碍传值/接收值
- spring mvc修改的问题解决思路
- 响应Return键
- (4.5.2.1)Android Studio教程02-Hello Word
- Android表情文字EmotionText解析
- 使用pthread_mutex_t锁的例子
- 数据库分库分表(sharding)系列
- struts1与struts2的区别
- MySQL数据导出与导入
- Installing the License Key for SCOM 2012
- 最简单地实现标签页导航-----TabLayout+ViewPager
- linux ps命令
- (4.5.2.2)Android Studio教程03-项目目录以及文件的详解