android 类似qq表情,android 实现类似qq表情
在自己做一个聊天应用练习的时候,需要用到表情,于是就想着模仿一下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表情相关推荐
- 教你如何创建类似QQ的android弹出菜单
热心推荐: Android ListView两种长按弹出菜单方式 popupwindow实现弹出菜单效果 Android人才招聘--最新招聘 大家可能看到 android 的自带的系统菜单比较难看, ...
- android 360 悬浮窗口,Android实现类似360,QQ管家那样的悬浮窗
一.前言: 我手机从来不装这些东西,不过,有次看到同事的android手机上,有个QQ管家在桌面上浮着,同事拖动管家时,管家就变成一只鸟,桌面下方还有个弹弓,桌面顶部有只乌鸦,把管家也就是鸟拖动到弹弓 ...
- JAVA开发Android聊天APP,实现了类似QQ、微信的即时通讯功能
视频学习地址 本内容接上篇文章 我的源码: 码云 github 大加有需要可以下载来参照一下. 文章目录 简介: 问题.报错 与视频中有差别的地方 视频的第十九节 视频的第38节,关于长按删除联系人, ...
- android实现qq表情库,Android编程开发之EditText实现输入QQ表情图像的方法
本文实例讲述了Android编程开发之EditText实现输入QQ表情图像的方法.分享给大家供大家参考,具体如下: 实现效果如下: 将QQ表情图像放到res下的drawable-hdpi文件夹下: 布 ...
- android 自定义园动画,Android 自定View实现仿QQ运动步数圆弧及动画效果
在之前的Android超精准计步器开发-Dylan计步中的首页用到了一个自定义控件,和QQ运动的界面有点类似,还有动画效果,下面就来讲一下这个View是如何绘制的. 1.先看效果图 2.效果图分析 功 ...
- android 仿qq 通讯录,Android端IM应用中的@人功能实现:仿微博、QQ、微信,零入侵、高可扩展[图文+源码]...
本文由"猫爸iYao"原创分享,感谢作者. 1.引言 最近有个需求:评论@人(没错,就是IM聊天或者微博APP里的@人功能),就像下图这样: WechatIMG43.jpg (19 ...
- QQ音乐Android客户端Web页面通用性能优化实践
QQ音乐 Android 客户端的 Web 页面日均 PV 达到千万量级,然而页面的打开耗时与 Native 页面相距甚远,需要系统性优化.本文将介绍 QQ 音乐 Android 客户端在进行 Web ...
- web 折线图大数据量拉取展示方案_【第2010期】QQ音乐Android客户端Web页面通用性能优化实践...
前言 今日早读文章由QQ音乐客户端开发工程师@关岳分享,公号:云加社区(ID:QcloudCommunity,腾讯云官方开发者社区)授权分享. 正文从这开始~~ QQ音乐 Android 客户端的 W ...
- android自定义设置界面,Android开发之精仿QQ设置界面(自定义PreferenceActivity)
Android开发之精仿QQ设置界面(自定义PreferenceActivity) 时间:2011-12-05 10:25:06 来源:Android开发者门户 作者: 今天,再给大家分享一下QQ设置 ...
- 【Android自定义View实战】之仿QQ运动步数圆弧及动画,Dylan计步中的控件StepArcView
转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/52936609 [DylanAndroid的csdn博客] 在之前的Androi ...
最新文章
- 数字孪生技术,让酷炫的智慧城市不再遥不可及
- 基于增强现实和脑机接口的机械臂控制系统
- adb查看手机cpu使用率_记录一下Unity打包Android在骁龙cpu上概率性卡死的问题
- 高行健---江西赣州人
- java tostring方法_Java虚拟机如执行方法调用的(二)?
- JAVA反射-面试题
- 原生jsonp发送跨域请求
- 源码文件编码问题,导致编译的程序运行错误
- 《系统工程》--课程笔记二(系统工程方法论)
- PowerBuilder反编译,PowerBuilder 反编译
- 黑苹果使用itlwm网卡驱动提示itlwm未运行的问题
- Android studio上音频文件格式问题
- Pycharm工具下的数据可视化(图形绘制)
- 英语六级常考核心词汇01
- 分段线性插值法实验报告_试验二插值法(含实验报告格式)-金锄头文库
- 转载:全志问题解决方法
- cogs426 血帆海盗 最小割定理
- 一文搞懂this指向
- 微信二次开发sdk非ipad/android协议(很好用)
- mysql var和varp的区别_了解T-SQL stdev、stdevp、var和varp