本文实例讲述了android编程实现qq表情的发送和接收。分享给大家供大家参考,具体如下:
在自己做一个聊天应用练习的时候,需要用到表情,于是就想着模仿一下qq表情,图片资源完全copy的qq.apk,解压就可以得到,这里不细说。
下面将该应用中的表情模块功能抽离出来,以便自己以后复习回顾。。
先看一下效果图:
首先进入界面:(完全仿照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程序设计有所帮助。