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

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

先看一下效果图:

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

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

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

点击发送:

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

下面列出一些关键代码:

表情工具类ExpressionUtil:

publicclassExpressionUtil {

/**

* 对spanableString进行正则判断,如果符合要求,则以表情图片代替

* @param context

* @param spannableString

* @param patten

* @param start

* @throws SecurityException

* @throws NoSuchFieldException

* @throws NumberFormatException

* @throws IllegalArgumentException

* @throws IllegalAccessException

*/

publicstaticvoiddealExpression(Context context,SpannableString spannableString, Pattern patten,intstart)throwsSecurityException, NoSuchFieldException, NumberFormatException, IllegalArgumentException, IllegalAccessException {

Matcher matcher = patten.matcher(spannableString);

while(matcher.find()) {

String key = matcher.group();

if(matcher.start()

continue;

}

Field field = R.drawable.class.getDeclaredField(key);

intresId = Integer.parseInt(field.get(null).toString());//通过上面匹配得到的字符串来生成图片资源id

if(resId !=0) {

Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);

ImageSpan imageSpan = 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对象,通过传入的字符串,并进行正则判断

* @param context

* @param str

* @return

*/

publicstaticSpannableString getExpressionString(Context context,String str,String zhengze){

SpannableString spannableString = newSpannableString(str);

Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE);        //通过传入的正则表达式来生成一个pattern

try{

dealExpression(context,spannableString, sinaPatten, 0);

} catch(Exception e) {

Log.e("dealExpression", e.getMessage());

}

returnspannableString;

}

}

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

SimpleChatAdapter中的内部类ViewHolder:

privateclassViewHolder{

RelativeLayout chat_layout;

ImageView image;

TextView text;

publicViewHolder(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);

}

publicvoidsetData(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:

/**

* 创建一个表情选择对话框

*/

privatevoidcreateExpressionDialog() {

builder = newDialog(MainActivity.this);

GridView gridView = createGridView();

builder.setContentView(gridView);

builder.setTitle("默认表情");

builder.show();

gridView.setOnItemClickListener(newOnItemClickListener() {

@Override

publicvoidonItemClick(AdapterView> arg0, View arg1,intarg2,

longarg3) {

Bitmap bitmap = null;

bitmap = BitmapFactory.decodeResource(getResources(), imageIds[arg2 % imageIds.length]);

ImageSpan imageSpan = newImageSpan(MainActivity.this, bitmap);

String str = null;

if(arg2<10){

str = "f00"+arg2;

}elseif(arg2<100){

str = "f0"+arg2;

}else{

str = "f"+arg2;

}

SpannableString spannableString = newSpannableString(str);

spannableString.setSpan(imageSpan, 0,4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

edit.append(spannableString);

builder.dismiss();

}

});

}

/**

* 生成一个表情对话框中的gridview

* @return

*/

privateGridView createGridView() {

finalGridView view =newGridView(this);

List> listItems = newArrayList>();

//生成107个表情的id,封装

for(inti =0; i <107; i++){

try{

if(i<10){

Field field = R.drawable.class.getDeclaredField("f00"+ i);

intresourceId = Integer.parseInt(field.get(null).toString());

imageIds[i] = resourceId;

}elseif(i<100){

Field field = R.drawable.class.getDeclaredField("f0"+ i);

intresourceId = Integer.parseInt(field.get(null).toString());

imageIds[i] = resourceId;

}else{

Field field = R.drawable.class.getDeclaredField("f"+ i);

intresourceId = 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 listItem = newHashMap();

listItem.put("image", imageIds[i]);

listItems.add(listItem);

}

SimpleAdapter simpleAdapter = 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;

}

android 类似qq表情,android 实现类似qq表情相关推荐

  1. 教你如何创建类似QQ的android弹出菜单

    热心推荐: Android  ListView两种长按弹出菜单方式 popupwindow实现弹出菜单效果 Android人才招聘--最新招聘 大家可能看到 android 的自带的系统菜单比较难看, ...

  2. android 360 悬浮窗口,Android实现类似360,QQ管家那样的悬浮窗

    一.前言: 我手机从来不装这些东西,不过,有次看到同事的android手机上,有个QQ管家在桌面上浮着,同事拖动管家时,管家就变成一只鸟,桌面下方还有个弹弓,桌面顶部有只乌鸦,把管家也就是鸟拖动到弹弓 ...

  3. JAVA开发Android聊天APP,实现了类似QQ、微信的即时通讯功能

    视频学习地址 本内容接上篇文章 我的源码: 码云 github 大加有需要可以下载来参照一下. 文章目录 简介: 问题.报错 与视频中有差别的地方 视频的第十九节 视频的第38节,关于长按删除联系人, ...

  4. android实现qq表情库,Android编程开发之EditText实现输入QQ表情图像的方法

    本文实例讲述了Android编程开发之EditText实现输入QQ表情图像的方法.分享给大家供大家参考,具体如下: 实现效果如下: 将QQ表情图像放到res下的drawable-hdpi文件夹下: 布 ...

  5. android 自定义园动画,Android 自定View实现仿QQ运动步数圆弧及动画效果

    在之前的Android超精准计步器开发-Dylan计步中的首页用到了一个自定义控件,和QQ运动的界面有点类似,还有动画效果,下面就来讲一下这个View是如何绘制的. 1.先看效果图 2.效果图分析 功 ...

  6. android 仿qq 通讯录,Android端IM应用中的@人功能实现:仿微博、QQ、微信,零入侵、高可扩展[图文+源码]...

    本文由"猫爸iYao"原创分享,感谢作者. 1.引言 最近有个需求:评论@人(没错,就是IM聊天或者微博APP里的@人功能),就像下图这样: WechatIMG43.jpg (19 ...

  7. QQ音乐Android客户端Web页面通用性能优化实践

    QQ音乐 Android 客户端的 Web 页面日均 PV 达到千万量级,然而页面的打开耗时与 Native 页面相距甚远,需要系统性优化.本文将介绍 QQ 音乐 Android 客户端在进行 Web ...

  8. web 折线图大数据量拉取展示方案_【第2010期】QQ音乐Android客户端Web页面通用性能优化实践...

    前言 今日早读文章由QQ音乐客户端开发工程师@关岳分享,公号:云加社区(ID:QcloudCommunity,腾讯云官方开发者社区)授权分享. 正文从这开始~~ QQ音乐 Android 客户端的 W ...

  9. android自定义设置界面,Android开发之精仿QQ设置界面(自定义PreferenceActivity)

    Android开发之精仿QQ设置界面(自定义PreferenceActivity) 时间:2011-12-05 10:25:06 来源:Android开发者门户 作者: 今天,再给大家分享一下QQ设置 ...

  10. 【Android自定义View实战】之仿QQ运动步数圆弧及动画,Dylan计步中的控件StepArcView

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/52936609 [DylanAndroid的csdn博客] 在之前的Androi ...

最新文章

  1. 数字孪生技术,让酷炫的智慧城市不再遥不可及
  2. 基于增强现实和脑机接口的机械臂控制系统
  3. adb查看手机cpu使用率_记录一下Unity打包Android在骁龙cpu上概率性卡死的问题
  4. 高行健---江西赣州人
  5. java tostring方法_Java虚拟机如执行方法调用的(二)?
  6. JAVA反射-面试题
  7. 原生jsonp发送跨域请求
  8. 源码文件编码问题,导致编译的程序运行错误
  9. 《系统工程》--课程笔记二(系统工程方法论)
  10. PowerBuilder反编译,PowerBuilder 反编译
  11. 黑苹果使用itlwm网卡驱动提示itlwm未运行的问题
  12. Android studio上音频文件格式问题
  13. Pycharm工具下的数据可视化(图形绘制)
  14. 英语六级常考核心词汇01
  15. 分段线性插值法实验报告_试验二插值法(含实验报告格式)-金锄头文库
  16. 转载:全志问题解决方法
  17. cogs426 血帆海盗 最小割定理
  18. 一文搞懂this指向
  19. 微信二次开发sdk非ipad/android协议(很好用)
  20. mysql var和varp的区别_了解T-SQL stdev、stdevp、var和varp

热门文章

  1. sscom32串口测试软件连接串口时有时会造成设备异常,更换别的串口软件后正常,特此记录
  2. 【VS2017】VS2017离线安装教程
  3. 一个完整的物联网项目管理流程
  4. 研究支付业务中,银行、支付机构与银联、网联的关系逻辑
  5. Python 上传文件到阿里云OSS
  6. STM32H743 SOEM EtherCAT基于STM32H743芯片和SOEM的EtherCAT主站源码 提供配套CUBE工程
  7. Mac版 matlab 安装 GAOT工具箱
  8. Java截取视频某一帧
  9. 最近好多K2PB1B2博通的官改版本被强制升级,下面是刷机办法。
  10. Hbase 深度使用分析