本文实例讲述了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程序设计有所帮助。