文档章节

Android表情的处理方案记录

叶大侠
 叶大侠
发布于 2015/07/21 13:27
字数 1206
阅读 2581
收藏 73

   

我们的目标,就是把表情的编码变成图片显示在文字中。在Android中,TextView本身已经支持了图文混排的样式。因此,在文字中插入一张表情图片并不困难,用下面的代码就可以做到了:

ImageSpan faceSpan = new ImageSpan(context, bmFace);
spannable.setSpan(faceSpan, faceStrat, faceEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

不过,事情往往没那么简单,让我们逐步看看会遇到什么问题。


1. 不同屏幕的表情如何适配?

为了尽量减少安装包的大小,表情肯定只能放一份在drawable中。那么,为了让表情在不同屏幕中显示的效果保持一致,我们就要设计成让表情图片可以按照dp的单位进行缩放。

faceSize = dpToPx(dp);
Bitmap bmFace = Bitmap.createScaledBitmap(bmSrcFace, faceSize, faceSize, true);

在表情不多的情况下,每一次都对表情图片进行缩放处理是没有什么问题的,但是我们都不知道用户究竟会输入多少表情。所以,为了减少表情的处理,我们需要对缩放后的表情图片进行缓存,以后直接取缩放的图片就好了。


2. 如何对缩放后的表情进行缓存?

在客户端的缓存设计中,一般都是采用这种三级的缓存策略,其中最下面的那层可能是来自远程服务器的。

这样,我们可以把表情的key值设计成:

drawable://drawableName?w=10&h=10

其中,drawableName是R.drawable.expression_smile 中的 "expression_smile" 部分, w为要取得表情图片的宽度,h为高度。

 单个表情的加载逻辑就大致如下:

Bitmap bmFace = memeryCache.getKey(faceDrawableUri);
if(bmFace == null){
   bmFace = diskCache.getKey(faceDrawableUri);
   if(bmFace == null){
       int drawableId = getDrawableIdFromUri(faceDrawableUri);
       int width = getDestWidth(faceDrawableUri);
       int height = getDestHeight(faceDrawableUri);
       Bitmap srcBitmap = loadFromDrawable(drawableId);
       bmFace = resize(srcBitmap , width , height );
       saveToDisk(bmFace);   
       memeryCache.putKey(faceDrawableUri,bmFace);
   }
}
return bmFace;

当然,这里还会牵涉到比较复杂的各级缓存池管理问题,我们在这里不展开。如果你是采用universalimageloader这个库的,那么你要做的就只是继承BaseImageDownloader,然后重写getStreamFromDrawable方法就可以了。

这里值得一提的是:为什么要用图片的名字,而不是drawable的Id值呢?要在drawable中加载图片是要使用int类型的Id值的呀!原因就是系统在R文件中生成的Id值每一次重新编译后产生的值都是不一样的,因此不能作为缓存的key, 所以需要多一步的反射R文件,把drawable的Id值取出来:

public static int getDrawableIdByName(String faceValue){
	if(DRAWABLE_ID_MAP.containsKey(faceValue)){  // DRAWABLE_ID_MAP用来缓存Drawable的Id
           return DRAWABLE_ID_MAP.get(faceValue);
	}
		
	try {
		Class<?> drawableClazz = R.drawable.class;
		java.lang.reflect.Field field = drawableClazz.getField(faceValue);
		int drawableId = field.getInt(DRAWABLE_INSTANCE);
		DRAWABLE_ID_MAP.put(faceValue, drawableId);
		return drawableId;
	} catch (NoSuchFieldException e) {
		DLog.e("the drawable " + faceValue + " doesn't exsits...");
		e.printStackTrace();
	} catch (IllegalAccessException e) {
		e.printStackTrace();
	} catch (IllegalArgumentException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return -1;
}

到这里为止,我们的表情图片尽可能快地获取到了。我们总结一下表情是如何加载到我们的文字中的先:

这里的关键就是ImageSpan对象所需要的表情图片的处理过程了,优先取内存中处理好的表情,这样的处理无疑可以加快了表情图片的加载速度,代价就是需要损耗更多的存储空间,对于用户体验的提示,这点空间不算太大,比如:

这里的表情有两种大小,那么,最终最多会在手机端产生3中尺寸的表情,按照表情的原大小5K一个计算,那一百个也就是1M左右,这是完全可以接受的。


3. 如何在ListView中进一步优化流畅度?

表情的处理到这里还没结束,如果你是要在ListView的Item中添加大量的表情,到目前为止,你还是会感到有比较强烈的卡顿现象的。没猜错的话,你应该是在ListAdapter的getView方法中对字符串进行了处理:


@Override
public View getView(final int position, View convertView, ViewGroup parent) {	
	...
        Model data = listData.get(position);
        CharSequence textSpannable = addFaceStyle(data.content);
	textView.setText(textSpannable);
}

这样相当于在UI线程进行了表情的处理,优化思路也比较明确,把addFaceStyle()的过程在后台返回的过程中就处理好,这样,content一开始就是添加了各种样式(包括表情,@人等样式)的Spannable类型对象。

//backgroud thread
public void doBackgroud(){
	Model data = requestRemote();
	data.content = addFaceStyle(data.content);
}

到此为此,出现较多的表情的ListView也能得到不错的流畅度了,优化是永无止境的,让我们先告一段落吧。


也可以阅读: http://www.darcye.com/article/63343732

© 著作权归作者所有

共有 人打赏支持
叶大侠

叶大侠

粉丝 58
博文 44
码字总数 67312
作品 5
广州
程序员
私信 提问
加载中

评论(6)

MarkJane
MarkJane
202105134
BeMyself
BeMyself
如何处理系统表情啊!
杰乐优
杰乐优
不错哦
王爵nice
王爵nice
mark
博文2014
博文2014
我知道了。
jonnykay
jonnykay
mark
移动可用性测试(三):移动现场测试方法和工具

1 现场测试还是远程测试 现场测试可以面对面接触用户,能够观察和记录所有的现场信息。远程测试虽然情境还原度较高,但通过摄像头和麦克风得到的信息毕竟有限,很多场外信息 包括用户肢体语言...

失足处男的倒霉孩子
2015/01/30
890
0
【OSC手机App技术解析】- 编辑框插入表情图片

众所周知,APP应用中带有表情功能,可以更好的提高用户体验。OSChina.NET Android版客户端v1.6 也加入表情功能,借此机会也给大家分享一下Android的编辑框是如何插入表情图片的,欢迎大家一起...

迷途d书童
2012/08/21
3.2K
2
Android系统操作的50个实用技巧

今天为大家整理的是Android系统操作的50个实用技巧,有利于大家更好的学习Sundy_android高级课程。请意这些技巧和秘籍大部分针对目前最主流的Android2.1 及以上系统,不过绝大部分在其他版本...

android技术开发
2013/07/25
358
1
Android P 版本号为 9,第三个开发者预览版有这些变化

近日,Google 如期放出了 Android P 的第三个开发者预览版(以下简称 DP3)。DP3 主要面向应用开发者,将该版本操作系统的 API 等级正式确定为 API level 28,开发者可以借助相关的 SDK 面向...

h4cd
06/10
2.8K
7
Android的TextView使用Html来处理图片显示、字体样式、超链接等

一、[Android实例]实现TextView里的文字有不同颜色 转eoe:http://www.eoeandroid.com/thread-4496-1-1.html 二、TextView显示html文件中的图片 转javaeye:http://da-en.javaeye.com/blog/7......

鉴客
2011/10/28
15.3K
3

没有更多内容

加载失败,请刷新页面

加载更多

《大漠烟尘》读书笔记及读后感文章3700字

《大漠烟尘》读书笔记及读后感文章3700字: 在这个浮躁的社会里,你有多久没有好好读完一本书了? 我们总觉得自己和别人不一样,所以当看到别人身上的问题时,很少有“反求诸己”,反思自己。...

原创小博客
38分钟前
1
0
大数据教程(9.5)用MR实现sql中的jion逻辑

上一篇博客讲解了使用jar -jar的方式来运行提交MR程序,以及通过修改YarnRunner的源码来实现MR的windows开发环境提交到集群的方式。本篇博主将分享sql中常见的join操作。 一、需求 订单数据表...

em_aaron
46分钟前
1
0
十万个为什么之什么是resultful规范

起源 越来越多的人开始意识到,网站即软件,而且是一种新型的软件。这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点...

尾生
52分钟前
1
0
Terraform配置文件(Terraform configuration)

Terraform配置文件 翻译自Terraform Configuration Terraform用文本文件来描述设备、设置变量。这些文件被称为Terraform配置文件,以.tf结尾。这一部分将讲述Terraform配置文件的加载与格式。...

buddie
今天
2
0
exportfs命令, vsftp搭建ftp服务

exportfs命令 当修改/etc/exports文件后,更改的内容是不会立即生效的。如果重启nfs服务,会导致客户端重启期间的请求是挂起等待的,可以把客户端的挂载umount进行卸载后,再重启nfs服务,但...

野雪球
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部