【问题标题】:Android TextView DrawableTint on pre v23 devicesv23 之前的设备上的 Android TextView DrawableTint
【发布时间】:2017-05-26 01:59:23
【问题描述】:

有什么方法可以为TextView 中使用的Drawable 着色? DrawableTint 仅适用于 API 级别 23 及以上。

目前我正在使用Vertical Linear Layout 来满足我的要求。

<LinearLayout style="@style/ChoiceIllustratorIconTextContainerStyle">

  <ImageView
    style="@style/ChoiceIllustratorImageStyle"
    android:contentDescription="@string/cd_university"
    android:src="@drawable/ic_account_balance_white_24dp" />

  <TextView
    style="@style/ChoiceIllustratorTextStyle"
    android:text="@string/ci_text_university" />

</LinearLayout>

看起来像,

Android 工作室建议我使用 Compound DrawbleTextView 来实现这一点。我能够实现它,但我找不到Tintdrawable 的方法。

<TextView
   style="@style/ChoiceIllustratorTextStyle"
   android:drawablePadding="4dp"
   android:drawableTop="@drawable/ic_account_balance_white_24dp"
   android:text="@string/ci_text_university" />

【问题讨论】:

标签: android textview xml-drawable


【解决方案1】:

AndroidX appcompat 库从 1.1.0-alpha03 版本开始支持在 TextView 中着色 [ref]

向 appcompat 库添加依赖项

dependencies {
  implementation "androidx.appcompat:appcompat:1.1.0"
}

然后可以像这样从 XML 中为 TextView 中的可绘制对象着色

<TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:drawableStartCompat="@drawable/ic_plus"
  app:drawableTint="@color/red" />

别忘了包含

xmlns:app="http://schemas.android.com/apk/res-auto"

并从AppCompatActivity 扩展您的活动。

【讨论】:

  • 他们应该将此添加到 ctrl+space 快捷方式中
【解决方案2】:

执行此操作的程序化方式是

       Drawable[] drawables = textView.getCompoundDrawables();
       if (drawables[0] != null) {  // left drawable
           drawables[0].setColorFilter(color, Mode.MULTIPLY);
       }

这适用于所有 API 级别。

这是预棉花糖设备的最佳选择。

【讨论】:

  • 如果您需要在另一个屏幕上使用不同的颜色或用于不同的视图状态,我相信您会想在调用 setColorFilter 之前mutate()drawable。
  • PorterDuff.Mode.MULTIPLY 对我不起作用。相反,PorterDuff.Mode.SRC_ATOP 对我有用。 PorterDuff.Mode.MULTIPLY 适合你吗?
  • SRC_ATOP 是 OP 所决定的,因此它也适用于您也就不足为奇了。记不清了,但我想我可能一直在使用全白像素的可绘制对象,因此 MULTIPLY 和 SRC_ATOP 看起来几乎相同。 OP 使用兼容性类的方法也是一个更好的选择。
  • 供参考:drawable[0] left, drawable[1] top, drawable[2] right, drawable[3] bottom。谢谢这个作品。
  • 感谢这工作。还要注意使用 getCompoundDrawablesRelative 作为开始/顶部/结束/底部
【解决方案3】:

此答案基于@kris larson 的建议。

我使用以下方法,它在所有设备上都可以正常工作。

setTintedCompoundDrawable 一个自定义方法,它采用 TextView 您想要设置复合可绘制对象、可绘制资源 ID & 以及您选择的颜色的资源 ID。

private void setTintedCompoundDrawable(TextView textView, int drawableRes, int tintRes) {
    textView.setCompoundDrawablesWithIntrinsicBounds(
            null,  // Left
            Utils.tintDrawable(ContextCompat.getDrawable(getContext(), drawableRes),
                    ContextCompat.getColor(getContext(), tintRes)), // Top
            null, // Right
            null); //Bottom
    // if you need any space between the icon and text.
    textView.setCompoundDrawablePadding(12);
}

Tint tintDrawable 方法如下:

public static Drawable tintDrawable(Drawable drawable, int tint) {
    drawable = DrawableCompat.wrap(drawable);
    DrawableCompat.setTint(drawable, tint);
    DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_ATOP);

    return drawable;
}

【讨论】:

  • 在从资源 id 加载的可绘制对象上调用 mutate() 以获取单独的可绘制对象,如果您在应用程序中的其他位置使用具有不同色调的可绘制资源。
【解决方案4】:

对于这种情况,您可以使用 TextViewCompat 类:

TextViewCompat.setCompoundDrawableTintList(TextView, ColorStateList)

【讨论】:

  • 这行不通。这将在 API v24 或更高版本上运行时始终生效
  • 使用@YouQi Compat类,表示支持所有版本
  • 您可能需要阅读该函数的文档:This will always take effect when running on API v24 or newer. When running on platforms previous to API v24, it will only take effect if textView implements the TintableCompoundDrawablesView interface. ```。鉴于问题的上下文低于 24,您的答案不够好,因为您没有解决完整的警告
  • 在 API 21 上与 MaterialTextView 配合使用效果很好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
相关资源
最近更新 更多