为什么将 ImageSpan 添加到 Snackbar 的操作文本可以在 Android 设备 SDK 级别 26 上工作,但不能在 SDK 级别 25 上工作?

Why does adding an ImageSpan to a Snackbar's action text work on Android devices SDK level 26 but not on SDK level 25?

我想显示一个 Snackbar 并使用图片而不是文本来执行操作。

我使用以下代码:

    val imageSpan = ImageSpan(this, R.drawable.star)
    val builder = SpannableStringBuilder(" ")
    builder.setSpan(
        imageSpan,
        0,
        1,
        SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE
    )
    Snackbar.make(findViewById(R.id.container), "Hello Snackbar", Snackbar.LENGTH_INDEFINITE)
        .setAction(builder) {}.show()

drawable_star 是矢量图形资产,但 png.

也是如此

在 Android 设备等级 26 及以上会产生:

符合预期,而在设备等级 25 上图像不可见:

有人知道这是什么原因吗?是否有解决方法?

PS:你可以在这里查看我的测试项目:https://github.com/fmweigl/SpannableTest

这是由于 Oreo 之前的版本存在 textAllCaps 错误。 Button 的默认样式将该属性设置为 true,这只会导致 Button 的文本全部转换为大写。该转换是通过 AllCapsTransformationMethod class 平台完成的,在 Nougat 7.1 及以下版本中,该平台会将所有内容视为平面 Strings,实质上会剥离您设置的任何格式跨度。

解决方法是关闭该属性,并在代码中处理您可能需要自己进行的任何大写转换。 Snackbar 提供 snackbarButtonStyle 属性作为给动作 Button 设置样式的方法,我们可以创建一个简单的样式来修改该值。例如,从您的 styles.xml:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <item name="snackbarButtonStyle">@style/NoCapsButton</item>>
</style>

<style name="NoCapsButton" parent="Widget.AppCompat.Button">
    <item name="textAllCaps">false</item>
</style>

(如果您使用的是 Material 组件主题,NoCapsButtonparent 应该改为 Widget.MaterialComponents.Button.TextButton.Snackbar。)


在这种特定情况下,这就是您需要做的所有事情,因为没有要转换的文本。