【问题标题】:ImageSpan not working on Android 5ImageSpan 不适用于 Android 5
【发布时间】:2015-08-27 19:08:00
【问题描述】:

我的这个功能在 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;
  }

当我调试时,一切似乎都成功了,但没有绘制图像。有什么想法我可能做错了吗?

【问题讨论】:

  • 我创建了一个 extends android.widget.Button 的类,尝试在运行 KitKat 的模拟器上使用您的 prependImage(Drawable, String) 方法,但图像绘制。
  • 嗯,应该有办法让它同时利用两者。我很高兴能把它扔掉,去做别的事情。您是否确定将可绘制对象的边界设置为 0,0,0,0 以外的值?
  • @i_am_jorf 您可以使用TextView 而不是Button。在所有 android 版本中,TextView 似乎都可以正常工作。
  • 在装有 Android 5.1.1 的 Nexus 5 上工作。你在哪里测试它?
  • 我正在三星 S6 (5.1) 和 S4 (4.4) 上进行测试。

标签: android imagespan


【解决方案1】:

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

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

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

看看here

【讨论】:

  • WTF Android...谢谢你
  • 你是上帝,谢谢你拯救我的一天:)
【解决方案2】:

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

问题在于 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作为你的按钮,然后设置带有图像的文本。

对于另一个(可能更正确),您需要以下一种方式扩展按钮样式(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) 中。

【讨论】:

  • 这似乎是最合理的解决方案。谢谢。
  • 我看到了这篇文章,我就像“让我们去吃点赏金吧”,但它已经解决了
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    适用于 Android 5.0+

    Drawable getDrawable(int id) 此方法在 API 级别已弃用 22. 改用 getDrawable(int, Theme)。

    Drawable getDrawable(int id, Resources.Theme theme) 返回一个drawable 与特定资源 ID 关联并为 指定主题。

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

    【讨论】:

    • 啊,对不起。我在MyButton 中有一个名为getDrawable(int id, int color) 的私有方法,它包装了对getContext().getResources().getDrawable(int id) 的调用,也调用了drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);。这会返回一个看起来完全合理的可绘制对象。
    【解决方案5】:

    试试这个

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

    【讨论】:

    • 使用带主题参数的新版本无效。
    猜你喜欢
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    • 2013-02-24
    相关资源
    最近更新 更多