Emoji’s World, 一起实现Emoji😀输入吧!

Emoji (絵文字 或 えもじ; 日语发音: [emodʑi]) 是日本无线通讯中所使用的视觉情感符号, 代表图形, 文字是图形本身的隐喻. 用于输入者表达情感信息, 如笑脸就代表开心😊, 蛋糕就代表食物🍰等. 形象生动, 在文字中出现图片, 更容易实现情感的表述.

Emoji起初只能在日本使用, 如今相当一部分的Emoji字符集已经被收入Unicode编码, 使其能被广泛应用. Android系统对于Emoji的原生支持从4.4版本开始. 对于文字输入型应用而言, 自定义的Emoji表情会大幅提升用户体验, 增强用户对于应用的辨识度, 也使输入更加有趣. 原生的Emoji表情由于需要适配多款机型, 节省存储空间, 所以设计得较为粗糙. 优秀美工重绘的Emoji表情, 一般都会更加符合用户的视觉习惯, 这就是QQ和微信大量重绘Emoji的原因.

本文介绍Emoji表情的实现方式, 具体效果参考春雨医生的在线问诊页面.

Emoji

下载Emoji列表

Emoji表情数据的存储方式有两种, 第一种在本地, 随着应用一起分发; 第二种在远程, 访问服务器获取. 显然第二种更为合理, 易于修改和替换, 方便重绘Emoji表情的后续扩容. 从远程服务器中获取Emoji数据时, 注意需要使用有序列表, 因为根据用户的使用习惯不同, 有些常用表情在先, 有些不常用在后. 考虑列表的有序性, 选择ArrayList-Pair数据结构传输, 而非Map, 因为列表是有序的, 而Map是无序的, 也可以选择LinkedHashMap.

本例Emoji数据集的数据结构是ArrayList>, 其中Pair的Key是Emoji的Unicode字符, Value是Emoji表情的下载地址.

在获取Emoji表情集合的全部表情下载地址后, 将这些表情缓存至本地, 统一更新, 减少访问远程服务器的次数, 节省流量和电量. 表情集合存储在BitmapLruCache类中, 即LRU缓存类, 其缓存模块使用内存(Memory)与本地硬盘(Disk)的二级缓存. 注意下载过程需要在非UI线程中进行, 即EmojiDownloadAsyncTasks.


缓存Emoji数据

为了快速地访问Emoji表情, 为其添加图片缓存必不可少. 本例的缓存类是BitmapLruCache, 其内部使用常见的二级缓存, 即内存缓存和硬盘缓存.

注意: 为了加快开发和减少错误, 尽量选择复用已有的轮子. 内存缓存使用Android系统自带的LruCache; 外存缓存使用DiskLruCache(Jake Wharton).

类中的addBitmapToCache方法, 将表情下载的url作为缓存映射Map的唯一Key. 下载后的Bitmap, 会优先写入外存缓存, 再同步写入内存缓存.

类中的getBitmapFromCache方法, 根据唯一标识下载url, 获取Bitmap. 优先从内存中获取, 当内存缓存不存在时, 从外存读取, 再同步写入内存; 当内存缓存存在时, 直接返回.

注意: Emoji表情一般都使用较小尺寸, 当图片加载入内存时, 防止图片过大, 优先进行压缩, 避免占用内存过多, 产生OOM. 尺寸大小支持外部配置.


管理Emoji数据

本例使用EmojiFileManager类作为Emoji表情集合的管理器, 同时作为接口, 向外部提供数据和方法. 原始的有序列表转换为无需映射HashMap, 便于快速查找表情; 转换为分页列表, 使用List>匹配ViewPager的表情分页显示.

类中convertPairList2Map的方法, 将ArrayList-Pair数据结构转换为HashMap, 加快Emoji表情的查找速度.; 类中convertPairToPageList的方法, 将原始结构ArrayList-Pair, 组合成EmojiIcon的数组, 再根据每页显示个数, 重构成二维数组, 用于ViewPager的表情分页显示.


替换Emoji表情

在字符串中, 替换Emoji表情的方式主要有两种: 第一种是在已有字符串中查找已经存在的Emoji编码, 替换为相应的表情; 第二种是创建单个Emoji表情的字符串.

类中的getExpressionString方法, 设置查找模式, 调用dealExpression替换相应Emoji表情, 并返回支持文字和图片的组合的SpannableString类型.

注意: 在Pattern中设置Pattern.UNICODE_CASE参数, 使其仅检查Unicode字符串, 缩小范围, 可以显著提升匹配速度, 否则在字符串较长时, 匹配速度较慢.

类中dealExpression方法查找匹配字符串, 调用addBitmap2Spannable替换图片, 并递归解析剩下的字符串, 直至全部替换完成. 具体步骤:

  1. 将所需替换的字符串与Emoji的Unicode标准编码匹配, 组成Matcher.
  2. 如果Matcher匹配成功, 则获取相应的字符串key.
  3. 如果Emoji字典中存在这个key, 则获取Emoji的对应url.
  4. 如果url存在, 则调用addBitmap2Spannable替换字符串为Emoji表情.
  5. 继续递归调用, 解析剩下的字符串.

类中的addBitmap2Spannable方法, 根据Emoji的url, 从图片缓存BitmapLruCache中获取相应的表情(Bitmap), 创建居中对齐的VerticalImageSpan, 与文字组合成SpannableString.

默认的ImageSpan参数不包含居中显示, 重写getSizedraw方法, 使ImageSpan居中对齐于文字, 注意位置数据的设置.

类中的addIcon方法, 创建单个Emoji表情的字符串. 通过addBitmap2Spannable方法, 将Emoji编码字符串替换为表情.


在需要替换Emoji表情的位置, 调用EmojiFileManagergetExpressionString方法, 将字符串中的Emoji编码替换为Emoji表情; 在需要添加Emoji表情的位置, 调用其addIcon方法获取单个Emoji表情, 与已存在的字符串, 拼接成最终字符串.

效果如下:

Emoji

为文字输入型应用添加Emoji表情吧, 让输入获得更多乐趣.

That’s all! Enjoy it!

请使用手机”扫一扫”x

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

1 1 收藏 评论

关于作者:Spike

硕士毕业, 任职于春雨移动健康, 从事移动端架构工作. 做了六年技术研发, 还会一直坚持下去. 分享一些自己的开发经验. 个人主页 · 我的文章 · 6 ·    

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部