ImageSpan 不适用于 Android 5

ImageSpan not working on Android 5

我的这个函数在 Android 4.4.1 上运行良好,但在 5.0+ 上运行不正常。

  public static SpannableStringBuilder prependImage(Drawable drawable, String text) {
    SpannableStringBuilder builder = new SpannableStringBuilder("  " + text);
    builder.setSpan(new ImageSpan(drawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    return builder;
  }

我是这样使用的:

class MyButton extends Button {

    // ... snip ...

    setText(
        prependImage(
            getDrawable(imageResource, color),                     
            getContext().getString(stringResource)),
        BufferType.SPANNABLE);

这是上面提到的 getDrawable() 方法:

 private Drawable getDrawable(int resource, int color) {
    final Resources resources = getContext().getResources();
    Drawable drawable = resources.getDrawable(resource);
    if (drawable != null) {
      drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
      drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    }
    return drawable;
  }

我调试的时候好像一切都成功了,就是画不出图。知道我可能做错了什么吗?

也许你需要检查那个Drawable对象的内容,你使用getDrawable()来获取Drawable对象,但是API定义似乎与你的调用参数不匹配。

For Android 5.0+

Drawable getDrawable(int id) This method was deprecated in API level 22. Use getDrawable(int, Theme) instead.

Drawable getDrawable(int id, Resources.Theme theme) Return a drawable object associated with a particular resource ID and styled for the specified theme.

第二个参数看起来像是主题,而不是颜色。对吗?

试试这个

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      getResources().getDrawable(R.drawable.your_drawable, getTheme());
            } else {
                getResources().
                        getDrawable(R.drawable.your_drawable);
            }

您与使用 Spannables 相关的代码没有问题。您可以通过为 TextView 设置文本来检查它。

问题出在material Android 5.0 的按钮设计中。

<style name="Widget.Material.Button">
    <item name="background">@drawable/btn_default_material</item>
    <item name="textAppearance">?attr/textAppearanceButton</item>
    <item name="minHeight">48dip</item>
    <item name="minWidth">88dip</item>
    <item name="stateListAnimator">@anim/button_state_list_anim_material</item>
    <item name="focusable">true</item>
    <item name="clickable">true</item>
    <item name="gravity">center_vertical|center_horizontal</item>
</style>

有两种解决方法。

第一个是使用 TextView 作为您的按钮,并使用带有图像的 setText。

对于另一个(可能更正确),您需要通过以下方式扩展按钮样式 (Widget.Material.Button):

<style name="BtnStyle" parent="android:Widget.Material.Button">
    <item name="android:textAppearance">@null</item>
</style>

然后在你的布局中:

<Button
    android:id="@+id/test2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Test"
    style="@style/BtnStyle"/>

完成后,您应该会在按钮中看到图像。

不要忘记对于低于 5.0 的 Android 版本你也应该创建 BtnStyle,但是在其他资源目录中(res/values-v14/style.xml)。

默认情况下,在 Material 中,按钮的样式设置为全部大写显示文本。但是,用于大写的 AllCapsTransformationMethod 中存在一个错误,导致它丢弃 Spannable 数据。

您可以通过在按钮上指定 android:textAllCaps="false" 来覆盖默认按钮样式并禁用全部大写。

<Button
    ...
    android:textAllCaps="false" />

看看

需要注意的一点是,可绘制矢量不起作用,您必须拥有一个 png 或 jpeg 可绘制对象,或者改为传递给 ImageSpan 位图