表情符号兼容性

EmojiCompat 支持库旨在使 Android 设备与最新的表情符号保持同步。它可以防止您的应用以 ☐ 的形式显示丢失的表情符号字符,这表示您的设备没有字体来显示文本。通过使用 EmojiCompat 支持库,您的应用用户无需等待 Android 操作系统更新即可获得最新的表情符号。

Devices showing emoji
图 1. 表情符号比较

请参阅以下相关资源

EmojiCompat 如何工作?

EmojiCompat 支持库提供类来在运行 Android 4.4(API 级别 19)及更高版本的设备上实现向后兼容的表情符号支持。您可以使用捆绑字体或可下载字体配置 EmojiCompat。有关配置的更多信息,请参阅以下部分

EmojiCompat 识别给定 CharSequence 的表情符号,如果需要,则将其替换为 EmojiSpans,最后渲染表情符号字形。图 2 演示了该过程。

EmojiCompat process
图 2. EmojiCompat 过程

可下载字体配置

可下载字体配置使用可下载字体支持库功能下载表情符号字体。它还会更新 EmojiCompat 支持库需要跟上 Unicode 规范最新版本所必需的表情符号元数据。

添加支持库依赖项

要使用 EmojiCompat 支持库,您必须在开发环境中修改应用项目的类路径依赖项。

向您的应用程序项目添加支持库

  1. 打开应用程序的 build.gradle 文件。
  2. 将支持库添加到 dependencies 部分。

Groovy

dependencies {
    ...
    implementation "androidx.emoji:emoji:28.0.0"
}

Kotlin

dependencies {
    ...
    implementation("androidx.emoji:emoji:28.0.0")
}

初始化可下载字体配置

您需要初始化 EmojiCompat 以加载元数据和字体。由于初始化可能需要一些时间,因此初始化过程在后台线程上运行。

要使用可下载字体配置初始化 EmojiCompat,请执行以下步骤

  1. 创建 FontRequest 类的实例,并提供字体提供程序权限、字体提供程序包、字体查询以及证书散列集列表。有关 FontRequest 的更多信息,请参阅 以编程方式使用可下载字体 部分在 可下载字体 文档中。
  2. 创建 FontRequestEmojiCompatConfig 的实例,并提供 ContextFontRequest 的实例。
  3. 通过调用 init() 方法并传递 FontRequestEmojiCompatConfig 的实例来初始化 EmojiCompat
  4. Kotlin

    class MyApplication : Application() {
    
        override fun onCreate() {
            super.onCreate()
            val fontRequest = FontRequest(
                    "com.example.fontprovider",
                    "com.example",
                    "emoji compat Font Query",
                    CERTIFICATES
            )
            val config = FontRequestEmojiCompatConfig(this, fontRequest)
            EmojiCompat.init(config)
        }
    }
    

    Java

    public class MyApplication extends Application {
      @Override
       public void onCreate() {
         super.onCreate();
         FontRequest fontRequest = new FontRequest(
           "com.example.fontprovider",
           "com.example",
           "emoji compat Font Query",
           CERTIFICATES);
         EmojiCompat.Config config = new FontRequestEmojiCompatConfig(this, fontRequest);
         EmojiCompat.init(config);
       }
    }
    
  5. 在布局 XML 中使用 EmojiCompat 小部件。如果您使用的是 AppCompat,请参阅 使用 EmojiCompat 小部件与 AppCompat 部分。
  6. <android.support.text.emoji.widget.EmojiTextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
    
    <android.support.text.emoji.widget.EmojiEditText
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
    
    <android.support.text.emoji.widget.EmojiButton
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
    

有关如何使用可下载字体配置配置 EmojiCompat 的更多信息,请访问表情符号兼容性示例应用 Java | Kotlin

库组件

Library components in EmojiCompat process
图 3. EmojiCompat 过程中的库组件
小部件:EmojiEditTextEmojiTextViewEmojiButton
默认小部件实现,用于将 EmojiCompatTextViewEditTextButton 一起使用。
EmojiCompat
支持库的主要公共表面。它执行所有外部调用并与系统的其他部分协调。
EmojiCompat.Config
配置要创建的单例实例。
EmojiSpan
一个 ReplacementSpan 子类,用于替换字符(序列)并渲染字形。
EmojiCompat 字体
EmojiCompat 使用字体来显示表情符号。此字体是 Android 表情符号字体 的修改版本。字体修改如下
  • 为了提供向后兼容性以渲染表情符号,所有表情符号字符都以 Unicode 的补充专用区域 A 中的单个 Unicode 代码点表示,从 U+F0001 开始。
  • 额外的表情符号元数据以二进制格式插入到字体中,并在运行时由 EmojiCompat 解析。数据嵌入到字体的 meta 表中,使用私有标签 Emji

配置选项

您可以使用 EmojiCompat 实例来修改 EmojiCompat 行为。您可以使用基类中的以下方法来设置配置

Kotlin

val config = FontRequestEmojiCompatConfig(...)
        .setReplaceAll(true)
        .setEmojiSpanIndicatorEnabled(true)
        .setEmojiSpanIndicatorColor(Color.GREEN)
        .registerInitCallback(object: EmojiCompat.InitCallback() {
            ...
        })

Java

EmojiCompat.Config config = new FontRequestEmojiCompatConfig(...)
       .setReplaceAll(true)
       .setEmojiSpanIndicatorEnabled(true)
       .setEmojiSpanIndicatorColor(Color.GREEN)
       .registerInitCallback(new InitCallback() {...})

添加初始化侦听器

EmojiCompatEmojiCompat 类提供 registerInitCallback()unregisterInitCallback() 方法来注册初始化回调。要使用这些方法,请创建 EmojiCompat.InitCallback 类的实例。调用这些方法并传递 EmojiCompat.InitCallback 类的实例。当 EmojiCompat 支持库的初始化成功时,EmojiCompat 类将调用 onInitialized() 方法。如果库初始化失败,EmojiCompat 类将调用 onFailed() 方法。

要随时检查初始化状态,请调用 getLoadState() 方法。它将返回以下值之一:LOAD_STATE_LOADINGLOAD_STATE_SUCCEEDEDLOAD_STATE_FAILED

在 AppCompat 组件中使用 EmojiCompat

如果您使用的是 AppCompat 组件,则可以使用扩展自 AppCompat 组件EmojiCompat 组件。

  1. 将支持库添加到依赖项部分。

    Groovy

    dependencies {
        ...
        implementation "androidx.emoji:emoji-bundled:$version"
    }
    

    Kotlin

          dependencies {
              implementation("androidx.emoji:emoji-appcompat:$version")
          }
          

    Groovy

          dependencies {
              implementation "androidx.emoji:emoji-appcompat:$version"
          }
          
  2. 在布局 XML 中使用 EmojiCompat AppCompat 组件 组件。
  3. <android.support.text.emoji.widget.EmojiAppCompatTextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
    
    <android.support.text.emoji.widget.EmojiAppCompatEditText
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
    
    <android.support.text.emoji.widget.EmojiAppCompatButton
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
    

捆绑字体配置

EmojiCompat 支持库也以捆绑字体版本提供。此软件包包含带有嵌入元数据的字体。该软件包还包括一个 BundledEmojiCompatConfig,它使用 AssetManager 加载元数据和字体。

注意: 字体的尺寸为几兆字节。

添加支持库依赖项

要将 EmojiCompat 支持库与捆绑字体配置一起使用,您**必须**在开发环境中修改应用项目的类路径依赖项。

向您的应用程序项目添加支持库

  1. 打开应用程序的 build.gradle 文件。
  2. 将支持库添加到 dependencies 部分。

Groovy

dependencies {
    ...
    implementation "androidx.emoji:emoji:28.0.0"
}

Kotlin

dependencies {
    ...
    implementation("androidx.emoji:emoji:28.0.0")
}

使用捆绑字体配置 EmojiCompat

要使用捆绑字体配置 EmojiCompat,请执行以下步骤

  1. 使用 BundledEmojiCompatConfig 创建 EmojiCompat 的实例,并提供 Context 的实例。
  2. 调用 init() 方法初始化 EmojiCompat,并传递 BundledEmojiCompatConfig 的实例。

Kotlin

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        val config = BundledEmojiCompatConfig(this)
        EmojiCompat.init(config)
    }
}

Java

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
        EmojiCompat.init(config);
        ...
    }
}

在没有组件的情况下使用 EmojiCompat

EmojiCompat 使用 EmojiSpan 渲染正确的图像。因此,它必须将任何给定的 CharSequence 转换为包含 EmojiSpanSpanned 实例。EmojiCompat 类提供了一种将 CharSequence 转换为包含 EmojiSpanSpanned 实例的方法。使用此方法,您可以处理和缓存已处理的实例而不是原始字符串,从而提高应用程序的性能。

Kotlin

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

Java

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

将 EmojiCompat 用于 IME

使用 EmojiCompat 支持库,键盘可以渲染其交互的应用程序支持的表情符号。IME 可以使用 hasEmojiGlyph() 方法检查 EmojiCompat 是否能够渲染表情符号。此方法采用表情符号的 CharSequence 并返回 true(如果 EmojiCompat 可以检测和渲染表情符号)。

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

在收到 EditorInfo.extras 捆绑包中的键后,键盘可以使用 hasEmojiGlyph() 方法(其中 metadataVersionEDITOR_INFO_METAVERSION_KEY 的值)来检查应用程序是否可以渲染特定表情符号。

将 EmojiCompat 与自定义组件一起使用

您始终可以使用 process() 方法预处理应用程序中的 CharSequence 并将其添加到任何可以渲染 Spanned 实例的组件中;例如,TextView。此外,EmojiCompat 提供了以下组件帮助程序类,让您可以轻松地为自定义组件添加表情符号支持。

TextView 示例

Kotlin

class MyTextView(context: Context) : AppCompatTextView(context) {

    private val emojiTextViewHelper: EmojiTextViewHelper by lazy(LazyThreadSafetyMode.NONE) {
        EmojiTextViewHelper(this).apply {
            updateTransformationMethod()
        }
    }

    override fun setFilters(filters: Array<InputFilter>) {
        super.setFilters(emojiTextViewHelper.getFilters(filters))
    }

    override fun setAllCaps(allCaps: Boolean) {
        super.setAllCaps(allCaps)
        emojiTextViewHelper.setAllCaps(allCaps)
    }
}

Java

public class MyTextView extends AppCompatTextView {
   ...
   public MyTextView(Context context) {
       super(context);
       init();
   }
   ...
   private void init() {
       getEmojiTextViewHelper().updateTransformationMethod();
   }

   @Override
   public void setFilters(InputFilter[] filters) {
       super.setFilters(getEmojiTextViewHelper().getFilters(filters));
   }

   @Override
   public void setAllCaps(boolean allCaps) {
       super.setAllCaps(allCaps);
       getEmojiTextViewHelper().setAllCaps(allCaps);
   }

   private EmojiTextViewHelper getEmojiTextViewHelper() {
       ...
   }
}
EditText 示例

Kotlin

class MyEditText(context: Context) : AppCompatEditText(context) {

    private val emojiEditTextHelper: EmojiEditTextHelper by lazy(LazyThreadSafetyMode.NONE) {
        EmojiEditTextHelper(this).also {
            super.setKeyListener(it.getKeyListener(keyListener))
        }
    }

    override fun setKeyListener(input: KeyListener?) {
        input?.also {
            super.setKeyListener(emojiEditTextHelper.getKeyListener(it))
        }
    }

    override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
        val inputConnection: InputConnection = super.onCreateInputConnection(outAttrs)
        return emojiEditTextHelper.onCreateInputConnection(
                inputConnection,
                outAttrs
        ) as InputConnection
    }
}

Java

public class MyEditText extends AppCompatEditText {
   ...
   public MyEditText(Context context) {
       super(context);
       init();
   }
   ...
   private void init() {
       super.setKeyListener(getEmojiEditTextHelper().getKeyListener(getKeyListener()));
   }

   @Override
   public void setKeyListener(android.text.method.KeyListener keyListener) {
       super.setKeyListener(getEmojiEditTextHelper().getKeyListener(keyListener));
   }

   @Override
   public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
       InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
       return getEmojiEditTextHelper().onCreateInputConnection(inputConnection, outAttrs);
   }

   private EmojiEditTextHelper getEmojiEditTextHelper() {
       ...
   }
}

常见问题

  • 如何启动字体下载?
  • 如果设备上不存在表情符号字体,则在第一次请求时下载。下载计划对应用程序是透明的。

  • 初始化需要多长时间?
  • 下载字体后,初始化 EmojiCompat 大约需要 150 毫秒。

  • EmojiCompat 支持库使用多少内存?
  • 目前,查找表情符号的数据结构加载到应用程序的内存中,大约使用 200KB。

  • 我可以在自定义 TextView 中使用 EmojiCompat 吗?
  • 可以。EmojiCompat 为自定义组件提供帮助程序类。也可以预处理给定的字符串并将其转换为 Spanned。有关组件帮助程序类的更多信息,请参阅将 EmojiCompat 与自定义组件一起使用部分。

  • 如果在运行 Android 4.4(API 级别 19)或更低版本的设备上在布局 XML 中添加组件会发生什么情况?
  • 您可以在支持运行 Android 4.4(API 级别 19)或更低版本的设备的应用程序中包含 EmojiCompat 支持库或其组件。但是,如果设备运行的是 Android 4.4 之前的版本,则 EmojiCompat 及其组件将处于“无操作”状态。这意味着 EmojiTextView 的行为与普通的 TextView 完全相同。EmojiCompat 实例;当您调用 init() 方法时,它将立即进入 LOAD_STATE_SUCCEEDED 状态。

其他资源

有关使用 EmojiCompat 库的更多信息,请观看EmojiCompat