Emoji兼容性

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

Devices showing emoji
图1. Emoji对比

请参考以下相关资源

EmojiCompat如何工作?

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

EmojiCompat 识别给定CharSequence 的Emoji,根据需要将其替换为EmojiSpans,最后呈现Emoji字形。图2演示了此过程。

EmojiCompat process
图2. EmojiCompat流程

可下载字体配置

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

添加支持库依赖项

要使用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 的更多信息,请访问Emoji Compatibility示例应用 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() {...})

添加初始化监听器

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

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

将 EmojiCompat 与 AppCompat 小部件一起使用

如果您正在使用 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 转换为带有 EmojiSpansSpanned 实例。EmojiCompat 类提供了一种方法,可以将 CharSequences 转换为带有 EmojiSpansSpanned 实例。使用此方法,您可以处理和缓存已处理的实例,而不是原始字符串,从而提高应用程序的性能。

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。

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

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

其他资源

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