android 实现类似qq表情

来源:互联网 发布:linux系统驱动开发 编辑:程序博客网 时间:2024/05/17 06:32

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

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

先看一下效果图:

首先进入界面:(完全仿照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.     /** 
  37.      * 得到一个SpanableString对象,通过传入的字符串,并进行正则判断 
  38.      * @param context 
  39.      * @param str 
  40.      * @return 
  41.      */  
  42.     public static SpannableString getExpressionString(Context context,String str,String zhengze){  
  43.         SpannableString spannableString = new SpannableString(str);  
  44.         Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE);        //通过传入的正则表达式来生成一个pattern  
  45.         try {  
  46.             dealExpression(context,spannableString, sinaPatten, 0);  
  47.         } catch (Exception e) {  
  48.             Log.e("dealExpression", e.getMessage());  
  49.         }  
  50.         return spannableString;  
  51.     }  
  52.       
  53.   
  54. }  


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

原文地址:http://blog.csdn.net/duancanmeng/article/details/7677144

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



原创粉丝点击