zoukankan      html  css  js  c++  java
  • Android Emoji兼容包使用详解

    Emoji兼容性

    我们经常会遇到这样的问题: 给朋友发的emoji表情, 在自己手机上展示是正常的, 但是到朋友手机上, 却没有展示出来, 或者展示出来了, 但是也跟自己手机上展示的不一样. 所以, 这是什么原因呢?

    要避免这种情况, 就需要使用Android Emoji的兼容包了. 

    Emoji兼容包目的在于保持Android设备拥有最新的Emoji. 它防止应用使用☐展示丢失的Emoji字符, 而☐意味着设备没有字体支持相应的文本. 通过使用EmojiCompat支持包, 应用的用户不必等候Android系统更新就可以获得最新的Emoji.

    EmojiCompat工作原理

    EmojiCompat支持包向运行Android 4.4(API 19)+的设备提供类以实现向后兼容的Emoji支持. 你可以配置EmojiCompat使用绑定的或者可下载的字体.

    EmojiComat识别指定的CharSequence, 如果必要的话, 会使用EmojiSpans代替它们, 并最终渲染成emoji符号.

    可下载字体配置

    可下载字体配置使用Downloadable Fonts支持包特性来下载emoji字体. 该支持包也更新必要的emoji元数据, EmojiCompat支持包需要与最新的Unicode版本保持一致.

    添加支持包依赖

    要使用EmojiCompat支持包, 必要要修改开发环境的应用工程路径依赖.
    要在应用中添加支持包, 需要:

    1. 打开应用build.gradle文件.
    2. 将依赖包添加到dependencies区域

     1 dependencies { 2 ... 3 compile "com.android.support:support-emoji:27.1.1" 4 } 

    初始化可下载字体配置

    你需要初始化EmojiCompat来下载元数据和字样. 因为初始化会花费一些时间, 所以初始化进程要运行在后台线程.

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

    • 创建FontRequest类实例并提供字体提供者权限, 字体提供者包, 字体查询以及认证的hash集列表. 
    • 创建FontRequestEmojiCompatConfig实例并提供Context实例和FontRequest.
    • 调用init()方法初始化EmojiCompat并传递FontRequestEmojiConfig实例
     1 public class MyActivity extends Activity {
     2     @Override
     3     public void onCreate() {
     4         super.onCreate();
     5         FontRequest fontRequest = new FontRequest(
     6                "com.example.fontprovider",
     7                "com.example",
     8                "emoji compat Font Query", CERTIFICATES);
     9         EmojiCompat.Config config = new FontRequestEmojiCompatConfig(this, fontRequest);
    10         EmojiCompat.init(config);
    11         ...
    12     }
    13 }
    • 在布局文件中使用EmojiCompat控件.
     1 <android.support.text.emoji.widget.EmojiTextView
     2    android:layout_width="wrap_content"
     3    android:layout_height="wrap_content"/>
     4 
     5 <android.support.text.emoji.widget.EmojiEditText
     6    android:layout_width="wrap_content"
     7    android:layout_height="wrap_content"/>
     8 
     9 <android.support.text.emoji.widget.EmojiButton
    10    android:layout_width="wrap_content"
    11    android:layout_height="wrap_content"/>

    包构件

    构件: EmojiEditText, EmojiTextView, EmojiButton. 这些构件是在TextView, EditText和Button上实现EmojiCompat的默认控件实现.

    • EmojiCompat: 支持包的主要公共接口. 它执行了所有的外部调用, 并与系统的其它部分协调.
    • EmojiCompat.Config: 配置要创建的单例.
    • EmojiSpan: ReplacementSpan子类, 取代字符(序列)并渲染字符.
    • EmojiCompat Font: EmojiCompat使用字体展示emoji. 字体是Android Emoji Font的修改版本. 字体接如下规则修改:
    1. 要提供向后兼容性来渲染emoji, 所有的emoji字符用单个Unicode码点表示, 这个码点位于Unicode Supplement Private Use Area-A, 从U+F001开始的
    2. 额外的emoji元数据以二进制格式插入字体, 并在运行时被EmojiCompat解析. 这些数据嵌套在字体的meta表中, 并含有私有标签Emji.

    配置选项

    你能够使用EmojiCompat实例修改EmojiCompat行为. 你可能使用源于基数的如下方法设置配置:

    • setReplaceAll(): 决定了EmojiCompat是否应该取代它用EmojiSpans找到的所有emoji. 默认情况下, EmojiCompat尽已所能理解系统是否能够渲染emoji, 但并不取代它们. 设置成true的时候, EmojiCompat会取代它用EmojiSpans找到的所有emoji.
    • setEmojiSpanIndicatorEnabled(): 指明EmojiCompat是否用EmojiSpan取代emoji. 设置成true的时候, EmojiCompat为EmojiSpan绘制背景. 但这个方法主要用于debug.
    • setEmojiSpanIndicatorColor(): 设置指明EmojiSpan的颜色. 默认值是GREEN.
    • registerInitCallback(): 告知应用EmojiCompat初始化的状态.
    1 EmojiCompat.Config config = new FontRequestEmojiCompatConfig(...)
    2        .setReplaceAll(true)
    3        .setEmojiSpanIndicatorEnabled(true)
    4        .setEmojiSpanIndicatorColor(Color.GREEN)
    5        .registerInitCallback(new InitCallback() {...})

    添加初始化监听器

    EmojiCompat类提供了registerInitCallback()和unregisterInitCallback()方法注册初始化回调. 要使用这些方法, 先创建EmojiCompat.InitCallback类, 调用这些方法, 然后传入EmojiCompat.InitCallback实例. 在EmojiCompat支持包初始化成功的时候, EmojiCompat类调用了onInitialized()方法. 如果库初始化失败了, EmojiCompat类调用onFailed()方法.

    要想在任何时刻查看初始化状态, 调用getLoadState()方法. 它返回下列值之一: LOAD_STATE_LOADING, LOAD_STATE_SUCCEED或者LOAD_STATE_FAILED.

    用AppCompat控件使用EmojiCompat

    如果你在使用AppCompat控件, 那么你可能使用继承自AppCompat控件的EmojiCompat控件.
    1, 添加如下依赖包.
     1 dependencies { 2 compile "com.android.support:support-emoji-appcompat:$version" 3 } 
    2, 在布局文件中使用EmojiCompat AppCompat Widget.

     1 <android.support.text.emoji.widget.EmojiAppCompatTextView
     2    android:layout_width="wrap_content"
     3    android:layout_height="wrap_content"/>
     4 
     5 <android.support.text.emoji.widget.EmojiAppCompatEditText
     6    android:layout_width="wrap_content"
     7    android:layout_height="wrap_content"/>
     8 
     9 <android.support.text.emoji.widget.EmojiAppCompatButton
    10    android:layout_width="wrap_content"
    11    android:layout_height="wrap_content"/>

    绑定字体配置

    EmojiCompat支持包绑定字体版本也是可用的. 这个包包含了嵌套元数据的字体. 也包含了使用AssetManager加载元数据和字体的BundledEmojiCompatConfig.
    备注: 字体大小有好几MB.

    添加支持包依赖

    要想使用EmojiCompat支持包的绑定字体配置, 你必须修改开发环境中应用工程的类路径依赖.
     1 dependencies { 2 ... 3 compile "com.android.support:support-emoji-bundled:$version" 4 } 

    使用绑定字体配置EmojiCompat

    要使用绑定字体配置EmojiCompat, 执行下列步骤:
    1, 使用BundledEmojiCompatConfig创建EmojiCompat实例并提供Context.
    2, 调用init()方法初始化EmojiCompat, 并传入BundledEmojiCompatConfig实例.

    1 public class MyActivity extends Activity {
    2     @Override
    3     public void onCreate() {
    4         super.onCreate();
    5         EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
    6         EmojiCompat.init(config);
    7         ...
    8     }
    9 }

    没有控件的情况下使用EmojiCompat

    EmojiCompat使用EmojiSpan渲染正确的图片. 由此, EmojiCompat必须使用EmojiSpans将给定CharSequence转化成Spanned. EmojiCompat类提供了方法通过EmojiSpans将CharSequence转化成Spanned对象. 通过这个方法, 你能够处理和缓存已处理实例, 而不是原生字符串, 由此提供了应用的性能.
     1 CharSequence processed = EmojiCompat.get().process("neutral face uD83DuDE10"); 

    IME使用EmojiCompat

    使用EmojiCompat支持包, 键盘通过渲染用户正在交互的应用支持的emoji. IME能够使用hasEmojiGlyph()方法检测EmojiCompat是否有能力渲染emoji. 这个方法将一个emoji CharSequence作为形参, 如果EmojiCompat能够检测和渲染这个emoji的话, 会返回true.

    键盘也能够检测应用支持的EmojiCompat支持包的版本, 以决定在画板中渲染哪个emoji. 要想检测这个版本, 如果可以的话, 键盘需要检测下列keys是否存在于EditorInfo.extras:

    • EDITOR_INFO_METAVERSION_KEY: 如果这个键存在, 这个值表示了应用使用的emoji元数据的版本. 如果这个键不存在, 应用不会使用EmojiCompat.
    • EDITOR_INFO_REPLACE_ALL_KEY: 如果该键存在且设置为true, 这表示应用调用了setReplaceAll()方法.

    在EditorInfo.extras中接收到键之后, 键盘能够使用hasEmojiGlyph()方法, 在这个方法里面, metadataVersion是键EDITOR_INFO_METAVERSION_KEY的值, 来检测应用是否能够渲染特定的emoji.

    在自定义控件中使用EmojiCompat

    在应用中, 你总是能够使用process()方法来预处理CharSequence并把它添加到任何能够渲染Spanned实例的控件中. 比如, TextView. 此外, EmojiCompat提供如下控件帮助类让你花费最小的代价就能使用emoji支持丰富自定义控件.

    • EmojiTextViewHelper
    • EmojiEditTextHelper

    Sample TextView:

     1 public class MyTextView extends AppCompatTextView {
     2    ...
     3    public MyTextView(Context context) {
     4        super(context);
     5        init();
     6    }
     7    ...
     8    private void init() {
     9        getEmojiTextViewHelper().updateTransformationMethod();
    10    }
    11 
    12    @Override
    13    public void setFilters(InputFilter[] filters) {
    14        super.setFilters(getEmojiTextViewHelper().getFilters(filters));
    15    }
    16 
    17    @Override
    18    public void setAllCaps(boolean allCaps) {
    19        super.setAllCaps(allCaps);
    20        getEmojiTextViewHelper().setAllCaps(allCaps);
    21    }
    22 
    23    private EmojiTextViewHelper getEmojiTextViewHelper() {
    24        ...
    25    }
    26 }


    Sample EditText:

     1 public class MyEditText extends AppCompatEditText {
     2    ...
     3    public MyEditText(Context context) {
     4        super(context);
     5        init();
     6    }
     7    ...
     8    private void init() {
     9        super.setKeyListener(getEmojiEditTextHelper().getKeyListener(getKeyListener()));
    10    }
    11 
    12    @Override
    13    public void setKeyListener(android.text.method.KeyListener keyListener) {
    14        super.setKeyListener(getEmojiEditTextHelper().getKeyListener(keyListener));
    15    }
    16 
    17    @Override
    18    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    19        InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
    20        return getEmojiEditTextHelper().onCreateInputConnection(inputConnection, outAttrs);
    21    }
    22 
    23    private EmojiEditTextHelper getEmojiEditTextHelper() {
    24        ...
    25    }
    26 }

    QA:

    • 我该如何初始化字体下载?

    如果Emoji字体在设备上并不存在, 那么在第一次请求的时候就会下载好. 下载调度对于应用是透明的.

    • 初始化花费多长时候?

    在字体下载好之后, 初始化EmojiCompat大约花费150ms.

    • EmojiCompat支持包占用多大内存?

    当前, 找到在应用内存中加载好的emoji并使用它的数据结构大约是200KB.

    • 自定义TextView可以使用EmojiCompat吗?

    是的, EmojiCompat为自定义控件提供帮助类. 它也能够预处理给定字符串并将转换成Spanned.

    • 如果我在运行Android 4.4(API 19) - 的设备上, 布局文件中添加了控件, 会发生什么?

    你能够在支持Android 4.4(API 19) - 的设备上引入EmojiCompat支持包或者它的控件. 然后, 如果设备运行的Android版本小于API 19, EmojiCompat和它的控件处理"no operation"状态. 这意味着EmojiTextView的行为就是一个常规的TextView. EmojiCompat实例, 在调用init()方法的时候, 马上就会进入LOAD_STATE_SUCCEED状态.

  • 相关阅读:
    linux之awk命令
    HDU 2097 Sky数 进制转换
    HDU 2077 汉诺塔IV
    HDU 2094 产生冠军 dfs加map容器
    HDU 2073 叠框
    HDU 2083 简易版之最短距离
    HDU 2063 过山车 二分匹配
    天梯 1014 装箱问题
    天梯 1214 线段覆盖
    天梯 1098 均分纸牌
  • 原文地址:https://www.cnblogs.com/littlepanpc/p/9284619.html
Copyright © 2011-2022 走看看