You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android低版本SDK中Unicode字符显示问题咨询

在低版本Android SDK中显示Unicode Emoji的解决方案

嘿,这个问题我维护旧版本Android应用的时候真的踩过坑!确实,高版本里用Html.fromHtml()能轻松显示的Emoji,到了低版本设备上就直接“失踪”,除了图片替代,其实还有几个更优雅的办法,给你详细说说:

1. 用官方EmojiCompat库(最推荐)

Google专门推出了这个库解决旧设备Emoji显示问题,省心还靠谱,支持API 19+:

  • 第一步:添加依赖
    在你的app模块build.gradle里加:
    implementation "androidx.emoji:emoji:1.2.0"
    // 如果需要支持更低版本,可以搭配emoji-appcompat依赖
    
  • 第二步:初始化库
    在Application的onCreate()里初始化:
    @Override
    public void onCreate() {
        super.onCreate();
        // 使用内置的Emoji字体包,也可以用下载式配置减少APK体积
        EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
        EmojiCompat.init(config);
    }
    
  • 第三步:使用Emoji
    要么直接在布局里用EmojiTextView替代普通TextView
    <androidx.emoji.widget.EmojiTextView
        android:id="@+id/emoji_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    
    要么给普通TextView处理文本:
    EmojiCompat.get().registerInitCallback(new EmojiCompat.InitCallback() {
        @Override
        public void onInitialized() {
            String emojiText = "\uD83C\uDFCC Golf \uD83C\uDFCC";
            textView.setText(EmojiCompat.get().process(emojiText));
        }
    });
    
    这个库会自动把系统不支持的Emoji替换成内置的渲染图形,完全不用自己操心字体的事!

2. 打包支持Emoji的自定义字体

如果你的APP需要支持API 19以下的极旧设备,这个方法兼容性拉满:

  • 选字体:找包含完整Emoji字形的字体,比如Noto Emoji、Google Sans Emoji,下载对应的.ttf.otf文件
  • 放资源:把字体文件放到src/main/assets/fonts目录下
  • 代码加载
    // 加载字体
    Typeface emojiFont = Typeface.createFromAsset(getAssets(), "fonts/NotoEmoji-Regular.ttf");
    // 给TextView设置字体(如果全是Emoji的话)
    textView.setTypeface(emojiFont);
    // 如果要混合普通文本和Emoji,用Spannable单独给Emoji部分设置字体
    SpannableString spannable = new SpannableString("\uD83C\uDFCC Golf \uD83C\uDFCC");
    spannable.setSpan(new TypefaceSpan(emojiFont), 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannable.setSpan(new TypefaceSpan(emojiFont), 7, 9, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(spannable);
    
    缺点是会增加APK体积(大概3-5MB),但胜在兼容性极强。

3. 用HtmlCompat替代原生Html.fromHtml

低版本Android的原生Html.fromHtml()对Unicode转义的支持很差,换成AndroidX的HtmlCompat会好很多:

String htmlText = "\uD83C\uDFCC Golf \uD83C\uDFCC";
textView.setText(HtmlCompat.fromHtml(htmlText, HtmlCompat.FROM_HTML_MODE_LEGACY));

不过这个方法还是依赖系统字体支持,如果系统本身没有Emoji字形,还是得配合上面的字体方案才行。

最后说说图片替代

如果以上方法都没法覆盖你的目标设备(比如API 10以下),那图片替代确实是最后的选择,但可以优化一下:用SpannableString把Emoji替换成ImageSpan,不用每个地方都写ImageView,稍微减少点繁琐度:

SpannableString spannable = new SpannableString("⛳ Golf ⛳");
// 替换第一个⛳
Drawable emojiDrawable = getResources().getDrawable(R.drawable.ic_emoji_golf);
emojiDrawable.setBounds(0, 0, emojiDrawable.getIntrinsicWidth(), emojiDrawable.getIntrinsicHeight());
ImageSpan imageSpan = new ImageSpan(emojiDrawable);
spannable.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 替换第二个⛳,重复操作
spannable.setSpan(imageSpan, 7, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannable);

总结一下:优先用EmojiCompat,省心又官方;需要极低版本兼容就用自定义字体;图片替代是实在没办法的选择。

内容的提问来源于stack exchange,提问作者AlienBuster

火山引擎 最新活动