typora-root-url: ./img


Android 开发,你遇上 Emoji 头疼吗?

在 Android 中,如果需要使用的到 Emoji 表情,你会发现在某些设备上,有一些 Emoji 表情会被以豆腐块 “☐” 的形式显示,这是因为当前设备并不支持这个 Emoji 表情。

而在 Android Support 中,新增加了一个 EmojiCompat 来专门解决这个问题,EmojiCompat 对 Android 4.4(Api Level 19)以及之后的系统,进行 Emoji 的扩展支持!

接下来我们就来了解使用 EmojiCompat 的所有细节!

一、什么是 Emoji?

既然要用到 Emoji ,我们先来了解一下什么是 Emoji。

Emoji 是可以被插入文字中的图形符号。它是一个日本语,e 表示"绘",moji 表示 "文字" ,连在一起就是 “绘文字”。

Emoji 最早是上个世纪 90 年代的时候,又日本电信商率先支持,就是为了在短信中,插入表情,来增强短信的体验。2007 年,Apple 在 iPhone 中支持了 Emoji,才让它在全球范围内流行起来。

早期的时候,Emoji 的实现是将一些特殊的符号组合替换成图片表情,例如 :) 替换成 ? ,这样的解决方案会导致很难将 Emoji 的表情标准化,而且表达的范围也有限。

2010年开始,Unicode 开始为 Emoji 分配码点,也就是说,在那之后的 Emoji 符号,就是一个字体,它会被渲染为图片显示。

Emoji 由于其表达情绪的特点,被广受欢迎。Emoji 的国际标准在 2015 年出台,现在已经是 5.0 版本了,而在 2018 年,将发布 Emoji 6.0(之后会重命名为 Emoji 11,其实就是 Emoji 5.0 的升级版) 版本的标准。

截止到现在,Emoji 5.0 中,被列入 Unicode 的已经有 2623 个了。

具体细节可以在这个网站中查询到:

http://www.unicode.org/emoji/charts/full-emoji-list.html

到这里大家应该清楚,Emoji 在标准化后,其实就是一个字体,它被 Unicode 分配了固定的码点,一般我们就用标准的 Unicode 来标识一个唯一的 Emoji。

虽然 Emoji 已经被标准化了,但是不同平台因为使用的字体不同,导致同样的 Unicode 代表的 Emoji,被渲染显示出不同的效果。

例如这里举的例子,标准的 Emoji U+1F601,在 Apple 和 Android 中,虽然同样表示一个笑脸,但是渲染的效果是不一样的,这一点我们需要了解到。

二、Emoji 在 Android 中的现状

2.1 如何使用 Emoji?

一个标准的 Emoji ,其实是有多种表示方法的,举个例子,先看看前面说的笑脸 U+1F601

Code、UTF-8、Surrogates 这些形式,都可以表示这个笑脸的 Emoji。通常这个 Emoji 表情是来自用户输入的数据或者服务端传递过来的数据,虽然这些形式都可以表示这个 Emoji,但是不同的格式就需要不同的形式来解析。

正常来说,我们推荐使用 Surrogates 传递 Emoji,例如:\uD83D\uDE01,它本身就是一个 Unicode 的编码,是通用的,可以在 TextView 中直接使用就可以显示。

可是,假如我们得到的并不是 Surrogates ,而是 Code ,例如 1F601,这样我们就需要进行额外的处理了。其实也很简单,经过几步转换就可以做到。

String(Character.toChars(Integer.parseInt("1F601", 16)))

例子中使用的是 Kotlin 代码,不过应该不影响阅读。

将生成的 String 对象,传递给 TextView,如果是当前设备支持的 Emoji,就可以正常显示了。

2.2 Emoji 显示不出来情况

上一小节介绍的方式,其实我们是没有做任何特殊处理的,完全是以来设备自己的字体库来进行 Emoji 渲染的。这就会导致有一些 Emoji 在某些设备上显示不出来的情况。

使用这种方案,我用我手边的设备运行之后,来看看显示的效果。

很清晰的看到,这里有一些 Emoji 无法显示,会被显示成一个豆腐块 “☐” ,而这并不是我们想要的。

接下来我们来看看使用 EmojiCompat 如何来处理它。

三、使用 EmojiCompat

3.1 什么是 EmojiCompat

根据官方文档描述,EmojiCompat 支持库主要是为了让 Android 设备,达到最新的 Emoji 符号的显示效果,它可以防止应用中,出现以豆腐块 “☐” 的形式来显示 Emoji,虽然它仅仅只是因为你当前的设备没有这个字体而已。通过 EmojiCompat ,你的设备无需等待 Android 系统更新,就可以获得最新的 Emoji 表情显示效果。

3.2 如何使用 EmojiCompat

EmojiCompat 支持库,最低支持到 Android 4.4(Api Level 19) 的系统设备。

EmojiCompat 提供两种字体的支持方式,它们分别是:

  1. 可下载的字体配置。
  2. 本地捆绑的字体配置。

这两种使用方式,除了引用的库不同之外,最根本的原因在于,可下载的字体的方式,会在首次启动的时候检查本地是否有该字体,没有的话会从网上下载最新的 Emoji 字体;而本地捆绑的方式,会在 App 打包的过程中,植入一个最新的 Emoji 字体文件,然后遇到不能支持的 Emoji,就会从这个字体文件中,加载资源并且渲染。

目前官方使用的是 NotoColorEmojiCompat.ttf 字体文件,后面会详细讲解到。

我想你应该发现了,本地捆绑的方式会嵌入一个字体文件,无形中增大了 Apk 安装包的体积,但是可下载字体的方式,又完全依赖 Google 服务,所以在国内基本上是处于残废状态,在这个大环境下,我们这里只能选择本地捆绑的方式来使用 EmojiCompat。

无论使用哪种方式配置字体,对于 EmojiCompat 而言,其实是不关心的,它只需要判断当前设备是否支持这个 Emoji,支持就使用系统内置的,不支持的话,就使用 EmojiSpans 来替换 CharSequence,来达到替换渲染的效果。

EmojiCompat 的运行原理如下图所示。

3.3 本地捆绑的字体配置方式

既然可下载的 Emoji 字体,需要配合 Google 服务,那这里就不再过多介绍了。

本文主要讲解如何使用本地捆绑的方式,使用 EmojiCompat。

第一步,需要添加 Gradle 依赖。

dependencies {...compile "com.android.support:support-emoji-bundled:27.0.2"
}

第二步,初始化 EmojiCompat。

初始化 EmojiCompat ,需要两个步骤。

  1. 首先需要生成一个 BundledEmojiCompatConfig 对象,它的构造方法接收一个 Context。
  2. 再调用 EmojiCompat.init() 方法,将前面生成的 config 传递给它进行初始化。

这个过程越早越好,因为初始化是耗时的,它会去加载打包的时候,嵌入的 Emoji 字体文件,所以大概需要消耗 150ms 的时间,并且占用大概 200kb 的内存。

第三步,使用 EmojiCompat。

初始化完成之后,就剩下如何使用它了。

EmojiCompat 的处理逻辑,前面已经使用图片描述清楚了。它会加载一个 Emoji 字体,然后判断当前设备是否支持需要显示的 Emoji,如果不支持,则使用 EmojiSpans 替换它,最终将处理过的 CharSequence 设置到 TextView 上。

而这个过程,EmojiCompat 提供了非常简单的方法,process()

从它的签名可以看出,它接受一个 CharSequence 并处理它,然后返回一个 CharSequence。

举个例子:这里转换一个笑脸的表情。

EmojiCompat.get().process("笑脸: \uD83D\uDE01")

process() 需要接受一个 Unicode 的字符,所以如果得到的数据是前面提到的 Emoji Code 的话,就需要一步单独的转换。process() 内部已经帮我们完成了转换,这些细节都无需我们关心,我们只需要将它返回的 CharSequence 设置给 TextView 就可以了。

3.4 Emoji AppCompat Widgets

在实际项目中,如果每次都需要通过 EmojiCompat.get().process() 对字符串进行处理,其实也挺麻烦的。为此 Google 还为开发者提供了对应控件支持。

如果需要使用它,就需要引入新的依赖库。

dependencies {compile "com.android.support:support-emoji-appcompat:27.0.2"
}

引入之后,就可以直接在 XML 中使用 EmojiAppCompat 提供的控件。

使用 support-emoji-appcompat 只是节省了我们 process() 的步骤,但是依然需要 init()

3.5 自定义控件支持 Emoji

你可以一直使用 progress() 或者使用 EmojiAppCompatXxx 控件,但是如果你想要自定义一个控件来显示 Emoji,就需要使用 EmojiCompat 提供的另外两个帮助类。

  • EmojiTextViewHelper
  • EmojiEditViewHelper

这两个使用起来非常简单,一个用于处理纯展示的控件,一个用于处理有输入的状态的控件,非常的简洁明了。

哪怕不记得了,看看 EmojiAppCompatTextView 和 EmojiAppCompatEditView 中的实现方式就可以了。

这里拿 EmojiAppCompatTextView 举例子,只需要在几个关键的位置上,使用 EmojiTextViewHelper 的对应方法即可。

3.6 EmojiCompat面临的问题

整体来说 EmojiCompat 还是很好用的,无论使用哪种方式加载它,实际上我们都不需要做过多的干预。

这里参考官方文档,列举最常见的几个问题。

1、下载字体的下载策略是怎么样的?

Emoji 字体在第一次使用的时候,会检测是否存在于当前设备,如果不存在则在子线程中进行下载。

2、初始化需要多长时间?

当本地已经有字体之后,初始化 EmojiCompat 大约需要 150 毫秒。

3、EmojiCompat 支持库,会使用多少内存?

目前,Emoji 字体被完全加载之后,会使用大约 200kb 的内存。

4、在 Android 4.4 以下的设备上,使用 EmojiAppCompatXxx 控件会发生什么情况?

EmojiCompat 内部已经做了兼容处理,在低版本上就和使用普通的 AppCompatXxx 控件一样。

5、本地捆绑的 Emoji 字体文件,大约有多大?

本地捆绑的 Emoji 字体文件 NotoColorEmojiCompat.ttf,会在打包的时候嵌入到 assets 目录下,现在实际情况来看大小有 7.4MB,这会直接造成 Apk 的增大。

更多的细节,还是建议大家阅读官方文档。

https://developer.android.google.cn/guide/topics/ui/look-and-feel/emoji-compat.html

四、EmojiCompat 的缺陷?

在实际使用 EmojiCompat 的过程中,还遇到了一个不能算缺陷的缺陷。

我们来回忆一下之前提到过的,EmojiCompat 的处理机制。

它只有在当前设备遇到不被支持的 Emoji 的时候,才会从 Support Font 中加载字体,如果有,它会使用 System Font 。

这也不能怪 EmojiCompat 的设计者,它的出发点,是为了解决 Emoji 在某些设备中,显示豆腐块 “☐” 的问题,而不关心它到底是不是显示最新的 Emoji,是在解决有无的问题。

这就很尴尬了,其实有时候 Android 设备内置支持的字体,显示的效果并不好,我们先来看看使用 EmojiCompat 前后的对比效果。

左边是没有使用 EmojiCompat 的效果,而右边是使用过的效果。

很清晰的可以看到 EmojiCompat 帮我补齐了我当前设备部支持的那些 Emoji 表情,但是并没有将 Android 的果冻表情替换为标准的 Emoji 表情。

那么,如果我们想要让它显示最新的 Emoji ,我们需要这么办呢?

前面提到,自从 Emoji 开始被标准化之后,其实就是一个字体,并且 EmojiCompat 也是帮我们捆绑嵌入了一个字体包在 assets 目录下,那我们只需要让我们显示的 TextView 加载这个 Emoji 字体,就可以解决这个问题。

有了思路,我们就来试试这个解决方案是否可行。

到此,我们就可以通过调用 loadEmoji() 方法,让 TextView 显示 Emoji ,来看看对比的效果。

从左到右,分别是:默认 Emoji、EmojiCompat、Emoji Font 的显示效果。

密密麻麻的表情有点多,密集恐惧症请放过我,?!

当然,这里只是提供一个解决方案,采用此方案的情况下,基本上所有 4.4 以上的机型,都可以显示最新的 Emoji,如果对 Emoji 的显示效果有要求,这也不失为一个解决方案。

五、总结

到此,就是我所了解的 Android 下的 Emoji。

看完本文你有什么收获?或者你有什么更好的关于 Emoji 的建议,欢迎在留言讨论!

今天在承香墨影公众号的后台,回复『成长』。我会送你一些我整理的学习资料,包含:Android反编译、算法、设计模式、虚拟机、Linux、Kotlin、Python、爬虫、Web项目源码。

推荐阅读:

  • 站在Android开发的角度,聊聊Airbnb的Lottie
  • Kotlin 一个好用的新功能:Parcelize !干掉序列化的模板代码
  • 找了一天找不到 Bug ? 试试 Git 的二分法吧!!!
  • 如何更精准的在 Github 上搜索开源库?你需要这些技巧!
  • 手写你的第一个 Dalvik 版的 HelloWorld !

转载于:https://www.cnblogs.com/plokmju/p/8143531.html

Android 开发,你遇上 Emoji 头疼吗?相关推荐

  1. Android开发举步维艰,上弘法寺七七四十九天取得“真经”!

    轶事 "老天爷保佑,在弘法寺烧的香还真显灵了!".在快要花光上一家公司的裁员赔偿款的4个月后,海投了200多家公司,面试了50多家,25岁在深圳的张鹏终于又"成功&quo ...

  2. android开发所遇问题集(一)----Mr.Zhang

    作为刚开始学习android开发的我,个人认为将从现在起记录在学习阶段所遇到的问题,这样将有益于我未来的学习,也可以帮助与我类似的初学者更好.更快的解决android开发过程中所遇到的问题. 今天我所 ...

  3. 汽车中控屏显示com点android,老车遇上安卓大屏导航中控的坑

    老车遇上安卓大屏导航中控的坑 2020-11-22 23:20:11 2点赞 0收藏 3评论 起因 事发在前天,我开着13款经典福去加油,加完之后打火,发现用了6年的飞歌车机不亮了.本来以为重新打火就 ...

  4. android edittext 输入法表情,Android开发中EditText禁止输入Emoji表情符

    在开发中可能多处会用到过滤Emoji表情符,一般情况下,我们会通过EditText的addTextChangedListener()监听来过滤Emoji表情,但在实际开发中会遇到多个EditText, ...

  5. Android开发文件上传格式,(android开发)使用okhttp上传文件

    开发android手机客户端,常常会需要上传文件到服务器,比如:你手机里的照片. 使用okhttp会是一个很好的选择.它使用很简单,而且运行效率也很高. 首先,在 app/build.gradle 的 ...

  6. 当开发人员遇上非功能性需求

    在开发产品时,你是否考虑过关注功能性需求与非功能性需求的工作量?如果没有,那么你可能应该关注下了,本文将告诉你为什么. 作者 | Chris Horsnell 译者 | 梁蕊 责编 | 仲培艺 出品 ...

  7. Android开发调用手机上安装的地图应用导航

    项目开发过程中需要调用地图应用进行导航,通常会使用百度地图和高德地图,调用地图看官方文档就可以搞定. 首先根据包名判断地图应用是否安装: 百度地图包名:com.baidu.BaiduMap 高德地图包 ...

  8. android开发实现头像上传功能

    刚进公司领导要求做个app头像上传功能,要求从相册或者相机拍照上传头像.网上参考了一些demo,整理了一下. 效果如图:         流程其实挺简单:对按钮进行监听,点击后弹出AlertDialo ...

  9. Unity3D开发之遇上Dropdown

    unity应该是在5.0版本更新了新的UI组件,Dropdown.以前实现这个功能都需要自己来组装.现在集成化确实对开发者来说更快更方便.下面说下我在开发中遇到的跟Dropdown相关的问题. uni ...

  10. Android学习总结(1)——好的 Android 开发习惯

    Android编码规范 java代码中不出现中文,最多注释中可以出现中文: 局部变量命名.静态成员变量命名:只能包含字母,单词首字母出第一个都为大写,其他字母都为小写: 常量命名:只能包含字母和 ,字 ...

最新文章

  1. catia怎么创建约束快捷键_答疑 | CATIA结构树无法显示怎么办?
  2. 软件测试中7个令人匪夷所思的真理
  3. dword类型和十进制有什么区别_微信小商店有几种类型,有什么区别?
  4. 连接到localhost后提示要求用户名和密码
  5. 红黑树:自平衡的二叉查找树
  6. Java如何配置ibmmq集群_如何在IBM MQ集群中动态创建订阅?
  7. maven学习(中)- 私服nexus搭建
  8. mysql nosql sqlite_自己做了一个轻量级的 NoSQL 数据库
  9. std::string的split函数
  10. 【XML】XML树形结构
  11. Spark cluster 安装
  12. 使用 IntraWeb (38) - TIWAppForm、TIWForm、TIWBaseHTMLForm、TIWBaseForm
  13. ROS IntelRealSenseZR300 PCL+ORK+Linemod 柱状物体检测 机械臂抓取 系列第二篇
  14. 达摩院发布:2022年十大科技趋势
  15. .NET面试宝典130道经典面试真题及答案
  16. google翻译的一个错误
  17. js正则 保留一位小数或者两位小数
  18. 电脑管理员权限在哪里可以打开
  19. 以太坊源码分析(39)geth启动流程分析
  20. MIPI_DSI协议

热门文章

  1. 产业分析:2021抖音数据报告
  2. JAVA经典算法题目
  3. java全碳硬叉好不_山地自行车跑长途为什么锁死避震前叉或者用硬叉好些?
  4. DLL Care破解版|DLL Care(DLL修复工具)破解版下载(附激活码)
  5. 十分钟学后端技术:怎么才能学好分布式系统和相关技术?
  6. 安卓手机屏幕投射电脑能同步声音
  7. 2023年厦门大学材料与化工考研考情与难度、参考书及上岸前辈初复试备考经验
  8. [imblearn]-欠采样模型合集
  9. 设置页数自增页眉/页脚——Word中page域代码的使用
  10. Office-014 显示域代码