安卓Emoji App Compat Text View无法渲染某些表情符号,例如

6
我正在尝试使用Emoji App Compat Text View,但我不明白我的实现有什么错误。
我正在尝试渲染这三个表情符号,在Android Q上可以正常工作,但在Android Lollipop上无法正常工作,请查看截图:
Android Q 上的截图 Android Lollipop 上的截图
Android Q 上的截图 Android Lollipop 上的截图
据我所知,使用 Emoji App Compat Text View 的想法是让 Android API 21 及更高版本的表情集能够正常工作,因此请查看我的实现是否有任何遗漏、错误或 Emoji App Compat Text View 不起作用。
您可以在github 上获取完整的代码,或者查看以下主要部分:
在应用程序的 onCreate 方法中设置 EmojiCompat,我没有使用捆绑版本:
EmojiCompat.init(
    FontRequestEmojiCompatConfig(
        this,
        FontRequest(
            "com.google.android.gms.fonts",
            "com.google.android.gms",
            "Noto Color Emoji Compat",
            R.array.com_google_android_gms_fonts_certs
        )
    ).setReplaceAll(true)
    // I did remove the callback for brevity, but I got the `onInitialized` called.
)

在Activity中,只需设置布局,获取View并设置文本:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
…
    <androidx.emoji.widget.EmojiAppCompatTextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="60sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<EmojiAppCompatTextView>(R.id.text_view).text = getString(R.string.three_emojis)
    }
}

字符串

<string name="three_emojis"></string>

gradle

plugins {
    id "com.android.application"
    id "kotlin-android"
}

android {
    compileSdkVersion 29
    buildToolsVersion "30.0.2"
…
    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 29
…
    }
…
}

dependencies {
    implementation "androidx.emoji:emoji-appcompat:1.1.0"
    implementation "androidx.emoji:emoji:1.1.0"
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation "androidx.appcompat:appcompat:1.2.0"
    implementation "androidx.constraintlayout:constraintlayout:2.0.4"
    implementation "androidx.core:core-ktx:1.3.2"
    implementation "com.google.android.material:material:1.2.1"
}

1
这是非常奇怪的行为。我已经尝试了来自https://emojipedia.org/eye/相同的表情符号,它可以正常工作。甚至看起来与您的表情符号相同。我还使用https://r12a.github.io/app-conversion/进行了比较,两个“眼睛”表情符号具有相同的数据。https://imgur.com/a/I9B7pSA - Haris
@HarisDautović 我无话可说,也不知道发生了什么,但我复制了你的示例并得到了相同的结果。我运行了 kotlinc-jvm""=="",左边是原始的,右边来自 emojipedia,结果是 res1: kotlin.Boolean = true - ademar111190
1
以下是一些额外的调试数据:https://imgur.com/a/fbFqvsa 数据值仅包含眼睛表情符号。情况1:不起作用 -> 解码后的表情符号有2个字符。 情况2:它起作用了 -> 解码后的表情符号有3个字符。第三个字符为空。 - Haris
1
@HarisDautović 我认为你说得很对,关于这个65039字符,它是变量选择器-16,根据维基百科的说法VS15和VS16保留用于请求将字符显示为文本或表情符号。所以为了测试它,我运行了.text = String(charArrayOf('\uD83D', '\uDC41')),但我没有得到表情符号。运行.text = String(charArrayOf('\uD83D', '\uDC41', 65039.toChar())),我得到了表情符号。而运行VS15.text = String(charArrayOf('\uD83D', '\uDC41', 65038.toChar())),我像预期的那样没有得到表情符号。 - ademar111190
1个回答

3

结论:默认情况下,将使用文本样式,除非在其后跟随U+FE0F变量选择器。

可以使用以下方法进行验证:

情况1:在所有Android版本上均返回false。

EmojiCompat.get().hasEmojiGlyph(String(charArrayOf('\uD83D', '\uDC41')))

案例2: 在Android API版本>=18上返回true

EmojiCompat.get().hasEmojiGlyph(String(charArrayOf('\uD83D', '\uDC41', 65039.toChar())))

Solution: .setUseEmojiAsDefaultStyle(true)

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
        EmojiCompat.init(
            FontRequestEmojiCompatConfig(
                this,
                FontRequest(
                    "com.google.android.gms.fonts",
                    "com.google.android.gms",
                    "Noto Color Emoji Compat",
                    R.array.com_google_android_gms_fonts_certs
                )
            ).setReplaceAll(true)
                .setUseEmojiAsDefaultStyle(true)
                .registerInitCallback(object : EmojiCompat.InitCallback() {
                    override fun onInitialized() {
                        super.onInitialized()
                        Toast.makeText(this@App, "EmojiCompat was initialized", LENGTH_SHORT).show()
                    }

                    override fun onFailed(throwable: Throwable?) {
                        super.onFailed(throwable)
                        throw RuntimeException(throwable)
                    }
                })
        )
    }
}

在Android API 19上测试过:

在这里输入图片描述


您很棒,提供了简单而有效的解决方案! - ademar111190
1
谢谢!我很欣赏你提出问题的方式。Demo Github项目非常有帮助。 - Haris
setUseEmojiAsDefaultStyle文档中说:“确定EmojiCompat是否应该使用表情符号表示样式来表示默认为文本样式的表情符号。”这意味着即使是数字和一些特殊字符也不会被表示为文本,而是作为表情符号。如果这是所需的行为,那么这很好,但如果不是,这个解决方案可能会非常丑陋,因为您将不得不定义一个完整的例外表情符号列表。 - Aleyam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接