先看一下效果图:

首先进入界面:(完全仿照QQ)

点击一下上面的表情图标:

选择一些表情,输入一些文字混合:

点击发送:

可以看到文字和表情图片都一起显示出来了。

下面列出一些关键代码:

表情工具类ExpressionUtil:

[java] view plaincopy
  1. public class ExpressionUtil {
  2. /**
  3. * 对spanableString进行正则判断,如果符合要求,则以表情图片代替
  4. * @param context
  5. * @param spannableString
  6. * @param patten
  7. * @param start
  8. * @throws SecurityException
  9. * @throws NoSuchFieldException
  10. * @throws NumberFormatException
  11. * @throws IllegalArgumentException
  12. * @throws IllegalAccessException
  13. */
  14. public static void dealExpression(Context context,SpannableString spannableString, Pattern patten, int start) throws SecurityException, NoSuchFieldException, NumberFormatException, IllegalArgumentException, IllegalAccessException {
  15. Matcher matcher = patten.matcher(spannableString);
  16. while (matcher.find()) {
  17. String key = matcher.group();
  18. if (matcher.start() < start) {
  19. continue;
  20. }
  21. Field field = R.drawable.class.getDeclaredField(key);
  22. int resId = Integer.parseInt(field.get(null).toString());       //通过上面匹配得到的字符串来生成图片资源id
  23. if (resId != 0) {
  24. Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
  25. ImageSpan imageSpan = new ImageSpan(bitmap);                //通过图片资源id来得到bitmap,用一个ImageSpan来包装
  26. int end = matcher.start() + key.length();                   //计算该图片名字的长度,也就是要替换的字符串的长度
  27. spannableString.setSpan(imageSpan, matcher.start(), end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);   //将该图片替换字符串中规定的位置中
  28. if (end < spannableString.length()) {                        //如果整个字符串还未验证完,则继续。。
  29. dealExpression(context,spannableString,  patten, end);
  30. }
  31. break;
  32. }
  33. }
  34. }
  35. /**
  36. * 得到一个SpanableString对象,通过传入的字符串,并进行正则判断
  37. * @param context
  38. * @param str
  39. * @return
  40. */
  41. public static SpannableString getExpressionString(Context context,String str,String zhengze){
  42. SpannableString spannableString = new SpannableString(str);
  43. Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE);        //通过传入的正则表达式来生成一个pattern
  44. try {
  45. dealExpression(context,spannableString, sinaPatten, 0);
  46. } catch (Exception e) {
  47. Log.e("dealExpression", e.getMessage());
  48. }
  49. return spannableString;
  50. }
  51. }

在显示聊天页面的list的适配器中,我们需要做如下的显示,即调用上面工具类的方法:

SimpleChatAdapter中的内部类ViewHolder:

[java] view plaincopy
  1. private class ViewHolder{
  2. RelativeLayout chat_layout;
  3. ImageView image;
  4. TextView text;
  5. public ViewHolder(View convertView){
  6. chat_layout=(RelativeLayout) convertView.findViewById(R.id.team_singlechat_id_listiteam);
  7. image=(ImageView) convertView.findViewById(R.id.team_singlechat_id_listiteam_headicon);
  8. text=(TextView) convertView.findViewById(R.id.team_singlechat_id_listiteam_message);
  9. }
  10. public void setData(MessageInfo msg){
  11. RelativeLayout.LayoutParams rl_chat_left=((RelativeLayout.LayoutParams)chat_layout.getLayoutParams());
  12. RelativeLayout.LayoutParams rl_tv_msg_left=((RelativeLayout.LayoutParams)text.getLayoutParams());
  13. RelativeLayout.LayoutParams rl_iv_headicon_left=((RelativeLayout.LayoutParams)image.getLayoutParams());
  14. if(!DicqConstant.DEFAULTMAC.equalsIgnoreCase(msg.getUsermac())){    //根据本地的mac地址来判断该条信息是属于本人所说还是对方所说
  15. //如果是自己说的,则显示在右边;如果是对方所说,则显示在左边
  16. rl_chat_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT,-1);
  17. rl_chat_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,0);
  18. rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT,-1);
  19. rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,0);
  20. rl_tv_msg_left.addRule(RelativeLayout.RIGHT_OF,R.id.team_singlechat_id_listiteam_headicon);
  21. rl_tv_msg_left.addRule(RelativeLayout.LEFT_OF,0);
  22. text.setBackgroundResource(R.drawable.balloon_l_selector);
  23. }else{
  24. rl_chat_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT,0);
  25. rl_chat_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,-1);
  26. rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_LEFT,0);
  27. rl_iv_headicon_left.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,-1);
  28. rl_tv_msg_left.addRule(RelativeLayout.RIGHT_OF,0);
  29. rl_tv_msg_left.addRule(RelativeLayout.LEFT_OF,R.id.team_singlechat_id_listiteam_headicon);
  30. text.setBackgroundResource(R.drawable.balloon_r_selector);
  31. }
  32. image.setImageResource(PrortaitUtils.conversionIdToRes(msg.getProtrait()));     //设置头像
  33. String str = msg.getMsg();                                                      //消息具体内容
  34. String zhengze = "f0[0-9]{2}|f10[0-7]";                                         //正则表达式,用来判断消息内是否有表情
  35. try {
  36. SpannableString spannableString = ExpressionUtil.getExpressionString(context, str, zhengze);
  37. text.setText(spannableString);
  38. } catch (NumberFormatException e) {
  39. e.printStackTrace();
  40. } catch (SecurityException e) {
  41. e.printStackTrace();
  42. } catch (IllegalArgumentException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. }

关于表情弹出框的实现如下:

MainActivity:

[java] view plaincopy
  1. /**
  2. * 创建一个表情选择对话框
  3. */
  4. private void createExpressionDialog() {
  5. builder = new Dialog(MainActivity.this);
  6. GridView gridView = createGridView();
  7. builder.setContentView(gridView);
  8. builder.setTitle("默认表情");
  9. builder.show();
  10. gridView.setOnItemClickListener(new OnItemClickListener() {
  11. @Override
  12. public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
  13. long arg3) {
  14. Bitmap bitmap = null;
  15. bitmap = BitmapFactory.decodeResource(getResources(), imageIds[arg2 % imageIds.length]);
  16. ImageSpan imageSpan = new ImageSpan(MainActivity.this, bitmap);
  17. String str = null;
  18. if(arg2<10){
  19. str = "f00"+arg2;
  20. }else if(arg2<100){
  21. str = "f0"+arg2;
  22. }else{
  23. str = "f"+arg2;
  24. }
  25. SpannableString spannableString = new SpannableString(str);
  26. spannableString.setSpan(imageSpan, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  27. edit.append(spannableString);
  28. builder.dismiss();
  29. }
  30. });
  31. }
  32. /**
  33. * 生成一个表情对话框中的gridview
  34. * @return
  35. */
  36. private GridView createGridView() {
  37. final GridView view = new GridView(this);
  38. List<Map<String,Object>> listItems = new ArrayList<Map<String,Object>>();
  39. //生成107个表情的id,封装
  40. for(int i = 0; i < 107; i++){
  41. try {
  42. if(i<10){
  43. Field field = R.drawable.class.getDeclaredField("f00" + i);
  44. int resourceId = Integer.parseInt(field.get(null).toString());
  45. imageIds[i] = resourceId;
  46. }else if(i<100){
  47. Field field = R.drawable.class.getDeclaredField("f0" + i);
  48. int resourceId = Integer.parseInt(field.get(null).toString());
  49. imageIds[i] = resourceId;
  50. }else{
  51. Field field = R.drawable.class.getDeclaredField("f" + i);
  52. int resourceId = Integer.parseInt(field.get(null).toString());
  53. imageIds[i] = resourceId;
  54. }
  55. } catch (NumberFormatException e) {
  56. e.printStackTrace();
  57. } catch (SecurityException e) {
  58. e.printStackTrace();
  59. } catch (IllegalArgumentException e) {
  60. e.printStackTrace();
  61. } catch (NoSuchFieldException e) {
  62. e.printStackTrace();
  63. } catch (IllegalAccessException e) {
  64. e.printStackTrace();
  65. }
  66. Map<String,Object> listItem = new HashMap<String,Object>();
  67. listItem.put("image", imageIds[i]);
  68. listItems.add(listItem);
  69. }
  70. SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.team_layout_single_expression_cell, new String[]{"image"}, new int[]{R.id.image});
  71. view.setAdapter(simpleAdapter);
  72. view.setNumColumns(6);
  73. view.setBackgroundColor(Color.rgb(214, 211, 214));
  74. view.setHorizontalSpacing(1);
  75. view.setVerticalSpacing(1);
  76. view.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
  77. view.setGravity(Gravity.CENTER);
  78. return view;
  79. }

Demo下载:http://download.csdn.net/detail/duancanmeng/4382260

转载自:http://blog.csdn.net/duancanmeng/article/details/7677144

完整实例实现QQ表情的发送和接收相关推荐

  1. 微信公众帐号开发教程第9篇-QQ表情的发送与接收

    我想大家对QQ表情一定不会陌生,一个个小头像极大丰富了聊天的乐趣,使得聊天不再是简单的文字叙述,还能够配上喜.怒.哀.乐等表达人物心情的小图片.本文重点要介绍的内容就是如何在微信公众平台使用QQ表情, ...

  2. [033] 微信公众帐号开发教程第9篇-QQ表情的发送与接收

    我想大家对QQ表情一定不会陌生,一个个小头像极大丰富了聊天的乐趣,使得聊天不再是简单的文字叙述,还能够配上喜.怒.哀.乐等表达人物心情的小图片.本文重点要介绍的内容就是如何在微信公众平台使用QQ表情, ...

  3. Android最完整的仿QQ表情聊天图文展示代码示例

    安卓最完整的表情聊天特效(大家可以看我上一篇文章websocket的整合,这是他的后续) 首先我们需要知道安卓输入的是EditText 显示的内容是TextView, 但是TextView里面又只能显 ...

  4. 微信公众帐号开发教程第11篇-符号表情的发送(上)

    题外话(可以略过) 相信这篇文章已经让大家等的太久了,不是我故弄玄虚.吊大家胃口,而是写一篇文章真的需要花太多的时间.也许一篇文章,你们花3-5分钟就看完了.就学会掌握了,而我却要花2-3个小时的时间 ...

  5. [11] 微信公众帐号开发教程第11篇-符号表情的发送(上)

    题外话(可以略过) 相信这篇文章已经让大家等的太久了,不是我故弄玄虚.吊大家胃口,而是写一篇文章真的需要花太多的时间.也许一篇文章,你们花3-5分钟就看完了.就学会掌握了,而我却要花2-3个小时的时间 ...

  6. [035] 微信公众帐号开发教程第11篇-符号表情的发送(上)

    题外话(可以略过) 相信这篇文章已经让大家等的太久了,不是我故弄玄虚.吊大家胃口,而是写一篇文章真的需要花太多的时间.也许一篇文章,你们花3-5分钟就看完了.就学会掌握了,而我却要花2-3个小时的时间 ...

  7. 二十一:微信公众帐号开发符号表情的发送上

    题外话(可以略过) 相信这篇文章已经让大家等的太久了,不是我故弄玄虚.吊大家胃口,而是写一篇文章真的需要花太多的时间.也许一篇文章,你们花3-5分钟就看完了.就学会掌握了,而我却要花2-3个小时的时间 ...

  8. 一种用QT实现即时通信软件表情发送与接收的思路

    一种用QT实现即时通信软件表情发送与接收的思路 最近需要使用QT为项目添加一个表情包发送与接受的功能,虽然之前知道表情发送与接收显示的一个基本原理,但是其中涉及到例如表情包插入到QTextEdit如何 ...

  9. 计算机网络课程设计——发送和接收TCP数据包以及发送和捕获ARP数据包

    1.课程设计要求: 发送和接收TCP数据包:TCP是一种面向连接的.可靠的传输层协议.TCP协议工作在网络层IP协议的基础上.本课程设计的目的是设计一个发送和接收TCP数据包的程序,其功能是填充一个T ...

最新文章

  1. Windows Server 2012 R2配置ISCSI磁盘共享盘(4)
  2. linux tf命令,Linux 基础命令
  3. 2017-07-18日看登录日志,显示十条:最早的是:2014-04-07 17:09,应该就是注册日期吧
  4. 关于mysql的ddl_log.log文件
  5. 学习笔记(39):Python实战编程-标签
  6. mysql中使用HAVING 筛选分组后的数据
  7. [html] websocket和http有什么区别?
  8. 开发 OpenAM Java 客户端
  9. NG2入门 - 架构
  10. WSL2 即将普遍可用,Linux 内核提供方式改变
  11. Jmeter_模板设置默认请求参数
  12. 《VC++深入详解》学习笔记 第十六章 线程同步与异步套接字编程
  13. Echarts.js+jquery.js+china.js实现中国疫情地图
  14. 最长回文串之中心扩散法
  15. Ant Design引入Echarts
  16. Linux 安装python 模块及库
  17. 软件中断SWI的实现
  18. cadence 617工艺库安装以及相关问题解决
  19. 2.1 压力泊松方程(OpenFOAM理论笔记系列)
  20. 草图logo绘画演绎AE模板

热门文章

  1. python编写一个程序、用户输入长方形的长和宽_Python:编写一个程序,要求用户提供颜色、线宽、行长和形状...
  2. 2023年美国大学生数学建模C题:预测Wordle结果建模详解+模型代码(一)
  3. Nagios 被动检测oracle Rman备份情况
  4. 解决cmd中启动mysql出现服务名无效或无法启动
  5. 地图下载1之天地图瓦片解析
  6. php微信获取模板id,微信模板消息示例
  7. 【Idea调试】Cannot resolve plugin org.springframework.boot:spring-boot-maven-plugin:3.0.1
  8. Web安全之SQL注入漏洞学习(七)-堆叠注入
  9. javaee学习之路(十五)JSP编程总结
  10. 如何下载 MySQL安装包