支持现代表情符号

尝试 Compose 方式
Jetpack Compose 是 Android 推荐的 UI 工具包。了解如何在 Compose 中支持表情符号。

标准表情符号集 每年由 Unicode 更新,因为表情符号在各种应用中的使用正在迅速增加。

如果您的应用显示互联网内容或提供文本输入,我们强烈建议您支持最新的表情符号字体。否则,较新的表情符号可能会显示为一个名为“豆腐块”的小方框 (☐) 或其他错误呈现的表情符号序列。

Android 11(API 级别 30)及更低版本无法更新表情符号字体,因此在这些版本上显示表情符号的应用必须手动更新。

以下是现代表情符号的示例。

示例 版本
🫩 🪉 🇨🇶 16.0(2024 年 9 月)
🐦‍🔥 🧑‍🧑‍🧒‍🧒 👩🏽‍🦽‍➡️ 🇲🇶 15.1(2023 年 9 月)
🩷 🫸🏼 🐦‍⬛ 15.0(2022 年 9 月)
🫠 🫱🏼‍🫲🏿 🫰🏽 14.0(2021 年 9 月)
😶‍🌫️ 🧔🏻‍♀️ 🧑🏿‍❤️‍🧑🏾 13.1(2020 年 9 月)
🥲 🥷🏿 🐻‍❄️ 13.0(2020 年 3 月)
🧑🏻‍🦰 🧑🏿‍🦯 👩🏻‍🤝‍👩🏼 12.1(2019 年 10 月)
🦩 🦻🏿 👩🏼‍🤝‍👩🏻 12.0(2019 年 2 月)

androidx.emoji2:emoji2 库提供了与较低版本 Android 更简单的向后兼容性。此 emoji2 库是 AppCompat 库的依赖项,无需进一步配置即可工作。

Compose 中的表情符号支持

BOM 2023 年 3 月 (Compose UI 1.4) 支持最新的表情符号版本,包括对旧版 Android(低至 API 21)的向后兼容性。本页面介绍了如何在 View 系统中配置现代表情符号。如需了解详情,请参阅Compose 中的表情符号页面。

前提条件

为了确认您的应用能正确显示较新的表情符号,请在运行 Android 10(API 级别 29)或更低版本的设备上启动应用。本页面包含可用于测试的现代表情符号。

使用 AppCompat 支持最新表情符号

AppCompat 1.4 包含对表情符号的支持。

如需使用 AppCompat 支持表情符号,请执行以下操作:

  1. 检查您的模块是否依赖于 AppCompat 库版本 1.4.0-alpha01 或更高版本。

    build.gradle
    
    // Ensure version is 1.4.0-alpha01 or higher.
    implementation "androidx.appcompat:appcompat.$appcompatVersion"
    
  2. 确保所有显示文本的 Activity 都扩展了 AppCompatActivity 类。

    Kotlin

    MyActivity.kt
    
    class MyActivity: AppCompatActivity {
    ...
    }

    Java

    MyActivity.java
    
    class MyActivity extends AppCompatActivity {
    ...
    }
  3. 在运行 Android 10 或更低版本的设备上启动应用并显示以下测试字符串,以测试您的集成。确保所有字符都能正确呈现。

    • 16.0: 🫩, 🪉, 🇨🇶
    • 15.1: 🐦‍🔥, 🧑‍🧑‍🧒‍🧒, 👩🏽‍🦽‍➡️, 🇲🇶
    • 15.0: 🩷, 🫸🏼, 🐦‍⬛
    • 14.0: 🫠, 🫱🏼‍🫲🏿, 🫰🏽
    • 13.1: 😶‍🌫️, 🧔🏻‍♀️, 🧑🏿‍❤️‍🧑🏾
    • 13.0: 🥲, 🥷🏿, 🐻‍❄️
    • 12.1: 🧑🏻‍🦰, 🧑🏿‍🦯, 👩🏻‍🤝‍👩🏼
    • 12.0: 🦩, 🦻🏿, 👩🏼‍🤝‍👩🏻

您的应用会在所有提供 emoji2 兼容的可下载字体提供程序(例如,由 Google Play 服务提供支持的设备)的设备上自动显示向后兼容的表情符号。

如果您的应用正在使用 AppCompat 但显示豆腐块 (☐)

在某些情况下,即使添加了 AppCompat 库,您的应用也可能会显示豆腐块而非正确的表情符号。以下是可能的原因和解决方案。

您正在刚刷新的设备或新模拟器上运行应用

清除应用的 Google Play 服务数据,以清除启动时可能发生的字体缓存。这通常会在几小时后解决问题。

如需清除应用数据,请执行以下操作:

  1. 在您的 Android 设备上打开 “设置”

  2. 点按 “应用和通知”

  3. 点按 “查看所有应用”“应用信息”

  4. 滚动查看应用并点按 “Google Play 服务”

  5. 点按 “存储空间和缓存”

  6. 点按 “清除缓存”

您的应用未使用 AppCompat 文本相关类

如果您未扩展 AppCompatActivity 或如果在代码中实例化视图(例如 TextView),则可能会发生这种情况。检查以下内容:

  • Activity 扩展了 AppCompatActivity
  • 如果在代码中创建视图,请使用正确的 AppCompat 子类

AppCompatActivity 会在膨胀 XML 时自动膨胀 AppCompatTextView 以代替 TextView,因此无需更新 XML。

测试手机不支持可下载字体

验证 DefaultEmojiCompatConfig.create 返回非 null 配置。

较低 API 级别上的模拟器未升级 Google Play 服务

在较低 API 级别上使用模拟器时,您可能需要更新捆绑的 Google Play 服务,以便 emoji2 找到字体提供程序。为此,请在模拟器上登录 Google Play 商店。

如需验证是否已安装兼容版本,请执行以下操作:

  1. 运行以下命令:

    adb shell dumpsys package com.google.android.gms | grep version
    
  2. 检查 versionCode 是否高于 211200000

不使用 AppCompat 支持表情符号

如果您的应用不能包含 AppCompat,则可以使用 emoji2 直接。这需要更多工作,因此仅当您的应用不能使用 AppCompat 时,才使用此方法。

如需在不使用 AppCompat 库的情况下支持表情符号,请执行以下操作:

  1. 在应用的 build.gradle 文件中,包含 emoji2emoji2-views

    build.gradle
    
    def emojiVersion = "1.0.0-alpha03"
    implementation "androidx.emoji2:emoji2:$emojiVersion"
    implementation "androidx.emoji2:emoji2-views:$emojiVersion"
    

    emoji2-views 模块提供了 子类TextViewButtonEditText,这些类实现了 EmojiCompat。不要在包含 AppCompat 的应用中使用此模块,因为它已实现 EmojiCompat

  2. 在 XML 和代码中(无论在何处使用 TextViewEditTextButton),请改用 EmojiTextViewEmojiEditTextEmojiButton

    activity_main.xml
    
    <androidx.emoji2.widget.EmojiTextView ... />
    <androidx.emoji2.widget.EmojiEditText ... />
    <androidx.emoji2.widget.EmojiButton ... />
    

    通过包含 emoji2 模块,系统会使用默认的可下载字体提供程序在应用启动后不久自动加载表情符号字体。无需进一步配置。

  3. 在运行 Android 11 或更低版本的设备上启动应用并显示以下测试字符串,以测试您的集成。确保所有字符都能正确呈现。

    • 16.0: 🫩, 🪉, 🇨🇶
    • 15.1: 🐦‍🔥, 🧑‍🧑‍🧒‍🧒, 👩🏽‍🦽‍➡️, 🇲🇶
    • 15.0: 🩷, 🫸🏼, 🐦‍⬛
    • 14.0: 🫠, 🫱🏼‍🫲🏿, 🫰🏽
    • 13.1: 😶‍🌫️, 🧔🏻‍♀️, 🧑🏿‍❤️‍🧑🏾
    • 13.0: 🥲, 🥷🏿, 🐻‍❄️
    • 12.1: 🧑🏻‍🦰, 🧑🏿‍🦯, 👩🏻‍🤝‍👩🏼
    • 12.0: 🦩, 🦻🏿, 👩🏼‍🤝‍👩🏻

不使用小部件使用 EmojiCompat

EmojiCompat 使用 EmojiSpan 呈现正确的图片。因此,它必须将任何给定的 CharSequence 对象转换为包含 EmojiSpan 对象的 Spanned 对象。EmojiCompat 类提供了 process() 方法来将 CharSequences 转换为 Spanned 实例。使用此方法,您可以在后台调用 process() 并缓存结果,从而提高应用的性能。

Kotlin

val processed = EmojiCompat.get().process("neutral face \uD83D\uDE10")

Java

CharSequence processed = EmojiCompat.get().process("neutral face \uD83D\uDE10");

为输入法编辑器使用 EmojiCompat

EmojiCompat 类允许键盘渲染其正在与之交互的应用支持的表情符号。输入法编辑器 (IME) 可以使用 getEmojiMatch() 方法检查 EmojiCompat 实例是否能够渲染表情符号。此方法接受一个表情符号的 CharSequence 并返回 true 如果 EmojiCompat 可以检测并渲染表情符号。

键盘还可以检查 EmojiCompat 应用支持的版本,以确定在调色板中渲染哪些表情符号。如需检查版本(如果可用),键盘可以在 EditorInfo.extras 捆绑包中查找以下键:

  • EDITOR_INFO_METAVERSION_KEY: 表示应用使用的表情符号元数据的版本。如果此键不存在,则表示应用未使用 EmojiCompat
  • EDITOR_INFO_REPLACE_ALL_KEY: 如果键存在且设置为 true,则应用将 EmojiCompat 配置为替换所有表情符号,即使系统已存在这些表情符号也是如此。

详细了解如何配置 EmojiCompat 实例

在自定义视图中使用表情符号

如果您的应用包含自定义视图TextView 的直接或间接子类,例如 ButtonSwitchEditText),并且这些视图可以显示用户生成的内容,则每个视图都必须实现 EmojiCompat

过程取决于您的应用是否使用 AppCompat 库。

为使用 AppCompat 的应用添加自定义视图

如果您的应用使用 AppCompat,请扩展 AppCompat 实现,而非平台实现。请参考下表,了解如何在 AppCompat 中扩展您的视图:

应扩展... 而非扩展...
TextView AppCompatTextView
EditText AppCompatEditText
ToggleButton AppCompatToggleButton
Switch SwitchCompat
Button AppCompatButton
CheckedTextView AppCompatCheckedTextView
RadioButton AppCompatRadioButton
CheckBox AppCompatCheckBox
AutoCompleteTextView AppCompatAutoCompleteTextView
MultiAutoCompleteTextView AppCompatMultiAutoCompleteTextView

为不使用 AppCompat 的应用添加自定义视图

如果您的应用不使用 AppCompat,请使用 emoji2-views-helper 模块中的视图集成帮助程序,这些帮助程序专为自定义视图设计。这些帮助程序是 AppCompat 库用来实现表情符号支持的帮助程序。

完成以下步骤,为不使用 AppCompat 的应用支持自定义视图。

  1. 添加 emoji2-views-helper

    implementation "androidx.emoji2:emoji2-views-helper:$emojiVersion"
    
  2. 按照说明,将 EmojiTextViewHelperEmojiEditTextHelper 添加到应用的自定义视图中。

  3. 在运行 Android 10 或更低版本的设备上启动应用并显示以下测试字符串,以测试您的集成。确保所有字符都能正确呈现。

    • 16.0: 🫩, 🪉, 🇨🇶
    • 15.1: 🐦‍🔥, 🧑‍🧑‍🧒‍🧒, 👩🏽‍🦽‍➡️, 🇲🇶
    • 15.0: 🩷, 🫸🏼, 🐦‍⬛
    • 14.0: 🫠, 🫱🏼‍🫲🏿, 🫰🏽
    • 13.1: 😶‍🌫️, 🧔🏻‍♀️, 🧑🏿‍❤️‍🧑🏾
    • 13.0: 🥲, 🥷🏿, 🐻‍❄️
    • 12.1: 🧑🏻‍🦰, 🧑🏿‍🦯, 👩🏻‍🤝‍👩🏼
    • 12.0: 🦩, 🦻🏿, 👩🏼‍🤝‍👩🏻

处理 emoji2 的可选功能

在应用中包含 emoji2 库后,您可以添加本节中介绍的可选功能。

配置 emoji2 使用不同的字体或可下载字体提供程序

如需将 emoji2 配置为使用不同的字体或可下载字体提供程序,请执行以下操作:

  1. 停用 EmojiCompatInitializer ,方法是将以下内容添加到清单中:

    <provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <meta-data android:name="androidx.emoji2.text.EmojiCompatInitializer"
               tools:node="remove" />
    </provider>
  2. 执行以下任一操作:

修改 EmojiCompat 行为

您可以使用 EmojiCompat.Config 的实例修改 EmojiCompat 行为。

最重要的配置选项是 setMetadataLoadStrategy(),它控制 EmojiCompat 何时加载字体。字体加载在调用 EmojiCompat.load() 后立即开始,并触发任何必要的下载。除非您的应用提供线程,否则系统会创建一个线程用于字体下载。

LOAD_STRATEGY_MANUAL 允许您控制何时调用 EmojiCompat.load(),而 LOAD_STRATEGY_DEFAULT 使加载在调用 EmojiCompat.init() 时同步开始。

大多数应用使用 LOAD_STRATEGY_MANUAL,以便控制字体加载的线程和时机。您的应用必须延迟加载,直到第一个屏幕显示后再进行,以避免引入启动延迟。EmojiCompatInitializer 遵循此做法,并延迟加载表情符号字体,直到第一个屏幕恢复后才进行。

使用基类中的以下方法设置配置的其他方面:

  • setReplaceAll(): 确定 EmojiCompat 是否将其找到的所有表情符号替换为 EmojiSpan 的实例。默认情况下,当 EmojiCompat 推断系统可以渲染某个表情符号时,它不会替换该表情符号。当设置为 true 时,EmojiCompat 会将所有表情符号替换为 EmojiSpan 对象。
  • setEmojiSpanIndicatorEnabled(): 指示 EmojiCompat 是否将表情符号替换为 EmojiSpan 对象。当设置为 true 时,EmojiCompat 会为 EmojiSpan 绘制背景。此方法主要用于调试。
  • setEmojiSpanIndicatorColor: 设置颜色以指示 EmojiSpan。默认值为 GREEN
  • registerInitCallback(): 通知应用 EmojiCompat 初始化状态。

添加初始化监听器

EmojiCompat 和 EmojiCompat.Config 类提供了 registerInitCallback()unregisterInitCallback() 方法来注册和注销初始化回调。您的应用可以使用这些回调等待,直到 EmojiCompat 初始化后再在后台线程或自定义视图中处理表情符号。

如需使用这些方法,请创建一个 EmojiCompat.InitCallback 类的实例。调用这些方法并传入 EmojiCompat.InitCallback 类的实例。当初始化成功时,EmojiCompat 类会调用 onInitialized() 方法。如果库初始化失败,EmojiCompat 类会调用 onFailed() 方法。

如需随时检查初始化状态,请调用 getLoadState() 方法。此方法返回以下值之一: LOAD_STATE_LOADINGLOAD_STATE_SUCCEEDED,或 LOAD_STATE_FAILED

使用 emoji2 支持捆绑字体

您可以使用 emoji2-bundled 工件将表情符号字体捆绑到应用中。但是,由于 NotoColorEmoji 字体超过 10MB,因此我们强烈建议您的应用在可能的情况下使用可下载字体。 emoji2-bundled 工件适用于不支持可下载字体的设备上的应用。

如需使用 emoji2-bundled 工件,请执行以下操作:

  1. 包含 emoji2-bundledemoji2 工件

    implementation "androidx.emoji2:emoji2:$emojiVersion"
    implementation "androidx.emoji2:emoji2-bundled:$emojiVersion"
    
  2. 配置 emoji2 使用捆绑配置

    Kotlin

    EmojiCompat.init(BundledEmojiCompatConfig(context))

    Java

    EmojiCompat.init(new BundledEmojiCompatConfig(context));
  3. 按照前面介绍的包含 emojicompat (带或不带 AppCompat)的步骤测试集成。确保测试字符串显示正确。

    • 16.0: 🫩, 🪉, 🇨🇶
    • 15.1: 🐦‍🔥, 🧑‍🧑‍🧒‍🧒, 👩🏽‍🦽‍➡️, 🇲🇶
    • 15.0: 🩷, 🫸🏼, 🐦‍⬛
    • 14.0: 🫠, 🫱🏼‍🫲🏿, 🫰🏽
    • 13.1: 😶‍🌫️, 🧔🏻‍♀️, 🧑🏿‍❤️‍🧑🏾
    • 13.0: 🥲, 🥷🏿, 🐻‍❄️
    • 12.1: 🧑🏻‍🦰, 🧑🏿‍🦯, 👩🏻‍🤝‍👩🏼
    • 12.0: 🦩, 🦻🏿, 👩🏼‍🤝‍👩🏻

自动 EmojiCompat 配置的影响

系统使用启动库 EmojiCompatInitializerDefaultEmojiCompatConfig 应用默认配置。

应用中的第一个 Activity 恢复后,初始化程序会安排加载表情符号字体。此短暂延迟可以让您的应用显示初始内容,而不会因在后台线程加载字体而产生任何潜在延迟。

DefaultEmojiCompatConfig 查找实现 EmojiCompat 接口的系统安装的可下载字体提供程序(例如 Google Play 服务)。在由 Google Play 服务提供支持的设备上,这会使用 Google Play 服务加载字体。

初始化程序会创建一个后台线程来加载表情符号字体,字体下载可能需要长达 10 秒才会超时。下载字体后,在后台线程上初始化 EmojiCompat 大约需要 150 毫秒。

推迟初始化 EmojiCompat,即使您停用 EmojiCompatInitializer 也是如此。如果您手动配置 EmojiCompat,请在应用显示第一个屏幕后调用 EmojiCompat.load(),以避免与第一个屏幕加载争用后台资源。

加载后,EmojiCompat 使用大约 300 KB 的 RAM 来保存表情符号元数据。