Android编程实现QQ表情的发送和接收完整实例(附源码)

时间:2022-08-22 17:17:35

本文实例讲述了android编程实现qq表情的发送和接收。分享给大家供大家参考,具体如下:

在自己做一个聊天应用练习的时候,需要用到表情,于是就想着模仿一下qq表情,图片资源完全copy的qq.apk,解压就可以得到,这里不细说。

下面将该应用中的表情模块功能抽离出来,以便自己以后复习回顾。。

先看一下效果图:

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

Android编程实现QQ表情的发送和接收完整实例(附源码)

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

Android编程实现QQ表情的发送和接收完整实例(附源码)

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

Android编程实现QQ表情的发送和接收完整实例(附源码)

点击发送:

Android编程实现QQ表情的发送和接收完整实例(附源码)

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

下面列出一些关键代码:

表情工具类expressionutil:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class expressionutil {
 /**
  * 对spanablestring进行正则判断,如果符合要求,则以表情图片代替
  * @param context
  * @param spannablestring
  * @param patten
  * @param start
  * @throws securityexception
  * @throws nosuchfieldexception
  * @throws numberformatexception
  * @throws illegalargumentexception
  * @throws illegalaccessexception
  */
 public static void dealexpression(context context,spannablestring spannablestring, pattern patten, int start) throws securityexception, nosuchfieldexception, numberformatexception, illegalargumentexception, illegalaccessexception {
  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 = integer.parseint(field.get(null).tostring()); //通过上面匹配得到的字符串来生成图片资源id
   if (resid != 0) {
    bitmap bitmap = bitmapfactory.decoderesource(context.getresources(), resid);
    imagespan imagespan = new imagespan(bitmap); //通过图片资源id来得到bitmap,用一个imagespan来包装
    int end = matcher.start() + key.length(); //计算该图片名字的长度,也就是要替换的字符串的长度
    spannablestring.setspan(imagespan, matcher.start(), end, spannable.span_inclusive_exclusive); //将该图片替换字符串中规定的位置中
    if (end < spannablestring.length()) { //如果整个字符串还未验证完,则继续。。
     dealexpression(context,spannablestring, patten, end);
    }
    break;
   }
  }
 }
 /**
  * 得到一个spanablestring对象,通过传入的字符串,并进行正则判断
  * @param context
  * @param str
  * @return
  */
 public static spannablestring getexpressionstring(context context,string str,string zhengze){
  spannablestring spannablestring = new spannablestring(str);
  pattern sinapatten = pattern.compile(zhengze, pattern.case_insensitive);  //通过传入的正则表达式来生成一个pattern
  try {
   dealexpression(context,spannablestring, sinapatten, 0);
  } catch (exception e) {
   log.e("dealexpression", e.getmessage());
  }
  return spannablestring;
 }
}

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

simplechatadapter中的内部类viewholder:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
private class viewholder{
  relativelayout chat_layout;
  imageview image;
  textview text;
  public viewholder(view convertview){
   chat_layout=(relativelayout) convertview.findviewbyid(r.id.team_singlechat_id_listiteam);
   image=(imageview) convertview.findviewbyid(r.id.team_singlechat_id_listiteam_headicon);
   text=(textview) convertview.findviewbyid(r.id.team_singlechat_id_listiteam_message);
  }
  public void setdata(messageinfo msg){
   relativelayout.layoutparams rl_chat_left=((relativelayout.layoutparams)chat_layout.getlayoutparams());
   relativelayout.layoutparams rl_tv_msg_left=((relativelayout.layoutparams)text.getlayoutparams());
   relativelayout.layoutparams rl_iv_headicon_left=((relativelayout.layoutparams)image.getlayoutparams());
   if(!dicqconstant.defaultmac.equalsignorecase(msg.getusermac())){ //根据本地的mac地址来判断该条信息是属于本人所说还是对方所说
   //如果是自己说的,则显示在右边;如果是对方所说,则显示在左边
    rl_chat_left.addrule(relativelayout.align_parent_left,-1);
    rl_chat_left.addrule(relativelayout.align_parent_right,0);
    rl_iv_headicon_left.addrule(relativelayout.align_parent_left,-1);
    rl_iv_headicon_left.addrule(relativelayout.align_parent_right,0);
    rl_tv_msg_left.addrule(relativelayout.right_of,r.id.team_singlechat_id_listiteam_headicon);
    rl_tv_msg_left.addrule(relativelayout.left_of,0);
    text.setbackgroundresource(r.drawable.balloon_l_selector);
   }else{
    rl_chat_left.addrule(relativelayout.align_parent_left,0);
    rl_chat_left.addrule(relativelayout.align_parent_right,-1);
    rl_iv_headicon_left.addrule(relativelayout.align_parent_left,0);
    rl_iv_headicon_left.addrule(relativelayout.align_parent_right,-1);
    rl_tv_msg_left.addrule(relativelayout.right_of,0);
    rl_tv_msg_left.addrule(relativelayout.left_of,r.id.team_singlechat_id_listiteam_headicon);
    text.setbackgroundresource(r.drawable.balloon_r_selector);
   }
   image.setimageresource(prortaitutils.conversionidtores(msg.getprotrait()));  //设置头像
   string str = msg.getmsg(); //消息具体内容
   string zhengze = "f0[0-9]{2}|f10[0-7]"; //正则表达式,用来判断消息内是否有表情
   try {
    spannablestring spannablestring = expressionutil.getexpressionstring(context, str, zhengze);
    text.settext(spannablestring);
   } catch (numberformatexception e) {
    e.printstacktrace();
   } catch (securityexception e) {
    e.printstacktrace();
   } catch (illegalargumentexception e) {
    e.printstacktrace();
   }
  }
}

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

mainactivity:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* 创建一个表情选择对话框
*/
private void createexpressiondialog() {
  builder = new dialog(mainactivity.this);
  gridview gridview = creategridview();
  builder.setcontentview(gridview);
  builder.settitle("默认表情");
  builder.show();
  gridview.setonitemclicklistener(new onitemclicklistener() {
   @override
   public void onitemclick(adapterview<?> arg0, view arg1, int arg2,
     long arg3) {
    bitmap bitmap = null;
    bitmap = bitmapfactory.decoderesource(getresources(), imageids[arg2 % imageids.length]);
    imagespan imagespan = new imagespan(mainactivity.this, bitmap);
    string str = null;
    if(arg2<10){
     str = "f00"+arg2;
    }else if(arg2<100){
     str = "f0"+arg2;
    }else{
     str = "f"+arg2;
    }
    spannablestring spannablestring = new spannablestring(str);
    spannablestring.setspan(imagespan, 0, 4, spannable.span_exclusive_exclusive);
    edit.append(spannablestring);
    builder.dismiss();
   }
  });
}
/**
* 生成一个表情对话框中的gridview
* @return
*/
private gridview creategridview() {
  final gridview view = new gridview(this);
  list<map<string,object>> listitems = new arraylist<map<string,object>>();
  //生成107个表情的id,封装
  for(int i = 0; i < 107; i++){
   try {
    if(i<10){
     field field = r.drawable.class.getdeclaredfield("f00" + i);
     int resourceid = integer.parseint(field.get(null).tostring());
     imageids[i] = resourceid;
    }else if(i<100){
     field field = r.drawable.class.getdeclaredfield("f0" + i);
     int resourceid = integer.parseint(field.get(null).tostring());
     imageids[i] = resourceid;
    }else{
     field field = r.drawable.class.getdeclaredfield("f" + i);
     int resourceid = integer.parseint(field.get(null).tostring());
     imageids[i] = resourceid;
    }
   } catch (numberformatexception e) {
    e.printstacktrace();
   } catch (securityexception e) {
    e.printstacktrace();
   } catch (illegalargumentexception e) {
    e.printstacktrace();
   } catch (nosuchfieldexception e) {
    e.printstacktrace();
   } catch (illegalaccessexception e) {
    e.printstacktrace();
   }
   map<string,object> listitem = new hashmap<string,object>();
   listitem.put("image", imageids[i]);
   listitems.add(listitem);
  }
  simpleadapter simpleadapter = new simpleadapter(this, listitems, r.layout.team_layout_single_expression_cell, new string[]{"image"}, new int[]{r.id.image});
  view.setadapter(simpleadapter);
  view.setnumcolumns(6);
  view.setbackgroundcolor(color.rgb(214, 211, 214));
  view.sethorizontalspacing(1);
  view.setverticalspacing(1);
  view.setlayoutparams(new layoutparams(layoutparams.fill_parent,layoutparams.wrap_content));
  view.setgravity(gravity.center);
  return view;
}

完整实例代码代码点击此处本站下载

希望本文所述对大家android程序设计有所帮助。