AppCompat 上的 TextView 色调

TextView tint on AppCompat

我用文本视图制作了一些复选框和单选按钮,但它们在 Lollipop 之前没有着色。

我的文本视图扩展 AppCompatCheckedTextView,样式为:

<style name="CheckBoxStyle" parent="android:Widget.TextView">
    <item name="android:textAppearance">?android:attr/textAppearance</item>
    <item name="android:drawableRight">?android:attr/listChoiceIndicatorMultiple</item>
    <item name="android:drawableEnd">?android:attr/listChoiceIndicatorMultiple</item>
    <item name="android:clickable">true</item>
    <item name="android:background">?attr/selectableItemBackground</item>
    <item name="android:gravity">center_vertical</item>
    <item name="android:paddingTop">8dp</item>
    <item name="android:paddingBottom">8dp</item>
</style>

并且我在我的主题中定义了我的口音:

<style name="AppTheme.Platform.NoActionBar" parent="Theme.AppCompat.NoActionBar">
    <item name="android:selectableItemBackground">@drawable/press_overlay_dark</item>
    <item name="android:borderlessButtonStyle">@style/BorderlessButton</item>

    <item name="android:colorAccent">@color/color_accent</item>
    <item name="colorAccent">@color/color_accent</item>
</style>

我正在针对 v21 进行构建,至少使用 v16 并使用 AppCompat v7-22.1.1。我的活动扩展 AppCompatActivity

AppCompat 中的小部件着色通过拦截任何布局 inflation 并在其 place.if 中插入小部件的特殊着色感知版本来工作 place.if 您有自己的小部件自定义版本,其中你的情况是 checkedtextview ,着色不起作用

来自小部件着色下的开发者博客

http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html

当 运行 在具有 Android 5.0 的设备上时,所有小部件都使用我们刚才谈到的颜色主题属性进行着色。在 Lollipop 上有两个主要功能允许这样做:drawable 着色和在 drawables 中引用主题属性(形式为 ?attr/foo)。

AppCompat 在 Android 的早期版本中为 UI 个小部件的子集提供了类似的行为:

AppCompat 工具栏提供的一切(操作模式等)

编辑文本

旋转器

复选框

单选按钮

切换(使用新的android.support.v7.widget.SwitchCompat)

CheckedTextView

您不需要做任何特别的事情来使这些工作正常,只需像往常一样在您的布局中使用这些控件,AppCompat 将完成其余的工作(有一些注意事项;请参阅下面的常见问题解答)。

查看 AppCompatCheckedTextView 的来源,我终于明白了。 它只为 checkMark 着色。由于它源自 CheckedTextView,而后者源自 TextView,因此 drawableRight 仅在棒棒糖上着色。查看 AppCompatTextView 的源代码,它只提供向后兼容的 textAllCaps所以 AFAIK,没有内置的方法来为 drawableRight 和类似的棒棒糖之前的颜色着色。 如果你想要一个更可定制的解决方案,你可能需要把你的 drawables 放在布局。

更新后的样式:

<style name="CheckBoxStyle" parent="android:Widget.TextView">
    <item name="android:textAppearance">@style/TextAppearance.AppCompat</item>
    <item name="android:checkMark">?android:attr/listChoiceIndicatorSingle</item>
    <item name="android:clickable">true</item>
    <item name="android:background">?attr/selectableItemBackground</item>
    <item name="android:gravity">center_vertical</item>
    <item name="android:paddingTop">8dp</item>
    <item name="android:paddingBottom">8dp</item>
</style>

我有一个色调问题。 AppCompatTextView 在低于 21 的 SDK 上 运行 时没有色调效果。我的解决方案是通过 java 设置色调颜色。 下面的示例有效。

xml

    <android.support.v7.widget.AppCompatTextView
    android:layout_width="50dp"
    android:layout_height="20dp"
    android:id="@+id/tvInfor2"
    android:background="@drawable/btn_style_black_border"
    android:gravity="center"
    android:backgroundTint="@color/colorPrimary"/>

java

    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if (currentapiVersion <= 21){
        tvInfor2.setSupportBackgroundTintList(getResources().getColorStateList(R.color.colorPrimary));
    }

对于Api 23级>= android:drawableTint="@color/colorPrimary"

对于Api级别:

JAVA

private void setTextViewDrawableColor(@RecentlyNonNull TextView textView,@ColorRes int color) {
        for (Drawable drawable : textView.getCompoundDrawables()) {
            if (drawable != null) {
                drawable.setColorFilter(new PorterDuffColorFilter(getColor(color), PorterDuff.Mode.SRC_IN));
            }
        }
    }

使用: setTextViewDrawableColor(txtMyDemoText,R.color.colorPrimary)


Kotlin 扩展函数

  fun TextView.setDrawableColor(@ColorRes color: Int) {
          compoundDrawables.filterNotNull().forEach {
              it.colorFilter = PorterDuffColorFilter(getColor(context, color), PorterDuff.Mode.SRC_IN)
        }
   }

使用: txtMyDemoText.setDrawableColor(R.color.colorPrimary)

这是一个向后兼容的 TextView。

用法:

<com.github.mrezanasirloo.TextViewCompatTint
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableStart="@drawable/ic_comment_black_14dp"
    app:drawableTint="@color/colorPrimary"
    tools:text="28"
    />

gist

不是对解决方案的直接回答。但是,如果您正在使用数据绑定并想要添加可绘制色调。查看以下示例:已在最新版本上测试,但也应该适用于 Api <=21

  @JvmStatic
    @BindingAdapter(value = ["app:drawableStart", "app:drawableStartTint"], requireAll = true)
    fun setDrawableStartTint(textView: TextView, @DrawableRes drawable: Drawable, @ColorInt color: Int) {
        val mutatedDrawable = drawable.mutate()
        mutatedDrawable.setColorFilter(color, PorterDuff.Mode.MULTIPLY)
        textView.setCompoundDrawablesWithIntrinsicBounds(mutatedDrawable, null, null, null)
    }

用法:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World"
    app:drawableStart="@{@drawable/ic_demo}"
    app:drawableStartTint="@{@color/color_demo_tint}"
 />

对于 API 23 岁及以上,只需在您的布局中设置它:android:drawableTint="@color/custom_color"

如果需要向后兼容,则需要以编程方式进行设置。在 Kotlin 中,您可以创建如下扩展函数:

fun TextView.setDrawableColor(@ColorRes color: Int) {
    compoundDrawables.filterNotNull().forEach {
        it.colorFilter = PorterDuffColorFilter(getColor(context, color), PorterDuff.Mode.SRC_IN)
    }
}

并像这样使用它:textView.setDrawableColor(R.color.custom_color)

请注意 filterNotNull() 在这里非常重要,因为可绘制对象列表可能会有一些空值(对于所有尚未设置的 TextView 可绘制对象)。

kotlin中:

fun TextView.setDrawableTintColor(colorRes: Int) {
  for (drawable in this.compoundDrawablesRelative) {
    drawable?.colorFilter = PorterDuffColorFilter(getColor(context, colorRes), PorterDuff.Mode.SRC_IN)
  }
}

用法:

myTextView.setDrawableTintColor(R.color.colorPrimary)

简化最上面的答案,它将是 Kotlin 中的扩展(但我​​没有检查):

fun TextView.setDrawableColor(@ColorRes color: Int) {
    val colorFilter = PorterDuffColorFilter(getColor(context, color), PorterDuff.Mode.SRC_IN)
    compoundDrawables.filterNotNull().forEach {
        it.colorFilter = colorFilter
    }
}

在所有对我不起作用的解决方案中,我创建了以下解决方案:

JAVA: 兼容 Api < 23

private void setTextViewDrawableColor(@RecentlyNonNull TextView textView,@ColorRes int color) {
        for (Drawable drawable : textView.getCompoundDrawablesRelative()) {
            if (drawable != null) {
                drawable.setColorFilter(new PorterDuffColorFilter(ContextCompat.getColor(textView.getContext(),color), PorterDuff.Mode.SRC_IN));
            }
        }
    }

使用

setTextViewDrawableColor(textView1,R.color.AccentColor)

KOTLIN

private fun setTextViewDrawableColor(@NonNull textView: TextView, @ColorRes color: Int) {
    for (drawable in textView.compoundDrawablesRelative) {
        if (drawable != null) {
            drawable.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(textView.context, color), PorterDuff.Mode.SRC_IN)
        }
    }
}

使用

setTextViewDrawableColor(textView1,R.color.AccentColor)

KOTLIN 扩展

fun TextView.setDrawableColor(@ColorRes color: Int) {
    compoundDrawablesRelative.filterNotNull().forEach {
        it.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(this.context, color), PorterDuff.Mode.SRC_IN)
    }
}

使用

textView1.setDrawableColor(R.color.colorAccent)

只有 XML API => 23

android:backgroundTintMode="src_in"
android:drawableTint="FF0000"