在自己做一个聊天应用练习的时候,需要用到表情,于是就想着模仿一下QQ表情,图片资源完全copy的QQ.apk,解压就可以得到,这里不细说。
下面将该应用中的表情模块功能抽离出来,以便自己以后复习回顾。。
先看一下效果图:
首先进入界面:(完全仿照QQ)
点击一下上面的表情图标:
选择一些表情,输入一些文字混合:
点击发送:
可以看到文字和表情图片都一起显示出来了。
下面列出一些关键代码:
表情工具类ExpressionUtil:
publicclassExpressionUtil{
/**
*对spanableString进行正则判断,如果符合要求,则以表情图片代替
*@paramcontext
*@paramspannableString
*@parampatten
*@paramstart
*@throwsSecurityException
*@throwsNoSuchFieldException
*@throwsNumberFormatException
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*/
publicstaticvoiddealExpression(Contextcontext,SpannableStringspannableString,Patternpatten,intstart)throwsSecurityException,NoSuchFieldException,NumberFormatException,IllegalArgumentException,IllegalAccessException{
Matchermatcher=patten.matcher(spannableString);
while(matcher.find()){
Stringkey=matcher.group();
if(matcher.start()
continue;
}
Fieldfield=R.drawable.class.getDeclaredField(key);
intresId=Integer.parseInt(field.get(null).toString());//通过上面匹配得到的字符串来生成图片资源id
if(resId!=0){
Bitmapbitmap=BitmapFactory.decodeResource(context.getResources(),resId);
ImageSpanimageSpan=newImageSpan(bitmap);//通过图片资源id来得到bitmap,用一个ImageSpan来包装
intend=matcher.start()+key.length();//计算该图片名字的长度,也就是要替换的字符串的长度
spannableString.setSpan(imageSpan,matcher.start(),end,Spannable.SPAN_INCLUSIVE_EXCLUSIVE);//将该图片替换字符串中规定的位置中
if(end
dealExpression(context,spannableString,patten,end);
}
break;
}
}
}
/**
*得到一个SpanableString对象,通过传入的字符串,并进行正则判断
*@paramcontext
*@paramstr
*@return
*/
publicstaticSpannableStringgetExpressionString(Contextcontext,Stringstr,Stringzhengze){
SpannableStringspannableString=newSpannableString(str);
PatternsinaPatten=pile(zhengze,Pattern.CASE_INSENSITIVE);//通过传入的正则表达式来生成一个pattern
try{
dealExpression(context,spannableString,sinaPatten,0);
}catch(Exceptione){
Log.e("dealExpression",e.getMessage());
}
returnspannableString;
}
}
在显示聊天页面的list的适配器中,我们需要做如下的显示,即调用上面工具类的方法:
SimpleChatAdapter中的内部类ViewHolder:
privateclassViewHolder{
RelativeLayoutchat_layout;
ImageViewimage;
TextViewtext;
publicViewHolder(ViewconvertView){
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);
}
publicvoidsetData(MessageInfomsg){
RelativeLayout.LayoutParamsrl_chat_left=((RelativeLayout.LayoutParams)chat_layout.getLayoutParams());
RelativeLayout.LayoutParamsrl_tv_msg_left=((RelativeLayout.LayoutParams)text.getLayoutParams());
RelativeLayout.LayoutParamsrl_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()));//设置头像
Stringstr=msg.getMsg();//消息具体内容
Stringzhengze="f0[0-9]{2}|f10[0-7]";//正则表达式,用来判断消息内是否有表情
try{
SpannableStringspannableString=ExpressionUtil.getExpressionString(context,str,zhengze);
text.setText(spannableString);
}catch(NumberFormatExceptione){
e.printStackTrace();
}catch(SecurityExceptione){
e.printStackTrace();
}catch(IllegalArgumentExceptione){
e.printStackTrace();
}
}
}
关于表情弹出框的实现如下:
MainActivity:
/**
*创建一个表情选择对话框
*/
privatevoidcreateExpressionDialog(){
builder=newDialog(MainActivity.this);
GridViewgridView=createGridView();
builder.setContentView(gridView);
builder.setTitle("默认表情");
builder.show();
gridView.setOnItemClickListener(newOnItemClickListener(){
@Override
publicvoidonItemClick(AdapterView>arg0,Viewarg1,intarg2,
longarg3){
Bitmapbitmap=null;
bitmap=BitmapFactory.decodeResource(getResources(),imageIds[arg2%imageIds.length]);
ImageSpanimageSpan=newImageSpan(MainActivity.this,bitmap);
Stringstr=null;
if(arg2<10){
str="f00"+arg2;
}elseif(arg2<100){
str="f0"+arg2;
}else{
str="f"+arg2;
}
SpannableStringspannableString=newSpannableString(str);
spannableString.setSpan(imageSpan,0,4,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
edit.append(spannableString);
builder.dismiss();
}
});
}
/**
*生成一个表情对话框中的gridview
*@return
*/
privateGridViewcreateGridView(){
finalGridViewview=newGridView(this);
List>listItems=newArrayList>();
//生成107个表情的id,封装
for(inti=0;i<107;i++){
try{
if(i<10){
Fieldfield=R.drawable.class.getDeclaredField("f00"+i);
intresourceId=Integer.parseInt(field.get(null).toString());
imageIds[i]=resourceId;
}elseif(i<100){
Fieldfield=R.drawable.class.getDeclaredField("f0"+i);
intresourceId=Integer.parseInt(field.get(null).toString());
imageIds[i]=resourceId;
}else{
Fieldfield=R.drawable.class.getDeclaredField("f"+i);
intresourceId=Integer.parseInt(field.get(null).toString());
imageIds[i]=resourceId;
}
}catch(NumberFormatExceptione){
e.printStackTrace();
}catch(SecurityExceptione){
e.printStackTrace();
}catch(IllegalArgumentExceptione){
e.printStackTrace();
}catch(NoSuchFieldExceptione){
e.printStackTrace();
}catch(IllegalAccessExceptione){
e.printStackTrace();
}
MaplistItem=newHashMap();
listItem.put("image",imageIds[i]);
listItems.add(listItem);
}
SimpleAdaptersimpleAdapter=newSimpleAdapter(this,listItems,R.layout.team_layout_single_expression_cell,newString[]{"image"},newint[]{R.id.image});
view.setAdapter(simpleAdapter);
view.setNumColumns(6);
view.setBackgroundColor(Color.rgb(214,211,214));
view.setHorizontalSpacing(1);
view.setVerticalSpacing(1);
view.setLayoutParams(newLayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
view.setGravity(Gravity.CENTER);
returnview;
}