为什么 parent 的背景会影响 child 视图的颜色?

Why does the parent's background affect the child views' color?

我的设置是一个 LinearLayout,其中包含一个 AppCompatImageView(我在其中显示矢量绘图)或一个 TextView(我在其中显示表情符号)。我通过 xml 将布局的 background 设置为 android:background="#FF0000",这使其显示为红色。问题是显示的图标和表情符号现在都变成了红色。下图显示了这种情况的两个实例(两次 parent 布局,一次使用 ImageView,一次使用 TextView)。

产生这个的xml(好吧,差不多,但问题就在那里):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical">
  <LinearLayout
      android:layout_marginTop="8dp"
      android:layout_marginBottom="8dp"
      android:layout_marginStart="8dp"
      android:layout_marginEnd="8dp"
      android:layout_width="24dp"
      android:layout_height="24dp"
      android:background="#FF0000">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text=""/>
  </LinearLayout>
  <LinearLayout
      android:layout_marginTop="8dp"
      android:layout_marginBottom="8dp"
      android:layout_marginStart="8dp"
      android:layout_marginEnd="8dp"
      android:layout_width="24dp"
      android:layout_height="24dp"
      android:background="#FF0000">
    <androidx.appcompat.widget.AppCompatImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:srcCompat="@drawable/ic_backspace_24"/>
  </LinearLayout>
</LinearLayout>

我发现 this question 与我观察到的症状完全相同。但是,似乎有一个 alpha 问题,我没有。我的所有 alpha 值都是 1.0f.

我发现 this question 询问关于 background 是通过影响所有 child 视图的主题设置的。但是因为它似乎改变了 child 视图的背景颜色,我不确定这与我的问题有什么关系。

我试过了(没有结果):

(我试图解决的实际问题是我的图标上有“白雾”。用红色测试显示图标会被背景染上颜色,所以我怀疑导致红色的原因也导致了初始我看到的是“白雾”。)

这是什么原因造成的?我该如何避免?

我能够使用 TextView 重现该问题。这似乎是因为默认主题中的文本颜色有一个小于 100% 的 alpha 组件,然后它也被应用于表情符号。因此,可以通过为任何文本颜色分配 100% alpha(或无 alpha 分量)来避免“色调”。

对于 ImageView,我怀疑与可绘制资源本身有关。如果您的退格图标是矢量可绘制对象,您还可以将代码添加到 post 或检查其填充颜色值。

这个问题有不同的方面。正如 所指出的,核心原因是表情符号和可绘制对象的颜色都有一个 alpha 分量。

可绘制对象

从 drawable 的代码可以明显看出它是用 ?attr/colorControlNormal:

着色的
<vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:width="24dp"
  android:height="24dp"
  android:viewportWidth="24"
  android:viewportHeight="24"
  android:tint="?attr/colorControlNormal">
  <path
    android:fillColor="@android:color/white"
    android:pathData="M22,3L7,3c-0.69,0 -1.23,0.35 -1.59,0.88L0,12l5.41,8.11c0.36,0.53 0.9,0.89 1.59,0.89h15c1.1,0 2,-0.9 2,-2L24,5c0,-1.1 -0.9,-2 -2,-2zM19,15.59L17.59,17 14,13.41 10.41,17 9,15.59 12.59,12 9,8.41 10.41,7 14,10.59 17.59,7 19,8.41 15.41,12 19,15.59z"/>
</vector>

这个颜色在我使用的主题中被定义为?android:attr/textColorSecondary。主题是新应用程序的默认主题(至少在我创建项目时):Theme.AppCompat.Light.DarkActionBar。这种颜色似乎是由设备定义的,但我不确定。至少在模拟器上,这种颜色有一个 alpha 分量。因此,无论背景颜色如何,将 tint 更改为 android:tint="#FF000000" 都会使图标变黑。

表情符号

进一步测试显示表情符号是用 android:textColorTertiary 着色的,这(在我的主题中)仅在 Base.TextAppearance.AppCompat.Small#android:textColor 中使用。我不知道它是如何与 TextView 的文本颜色相关联的,但至少我知道如何更改它:

textView.setTextColor(Color.parseColor("#FF000000"))

styles.xml:

<item name="android:textColorTertiary">#FF000000</item>

这会使表情符号变得不透明,因为颜色的 alpha 通道为 100%。