具有唯一 ID 的布局上的 setBackgroundColor 也会更改其他布局上的颜色

setBackgroundColor on a layout with a unique id also changes the color on other layouts

我有一个 RelativeLayout 具有唯一 ID 和此配置:

android:background="@color/popup_background"

popup_background 的值为 #EDEDED,还有其他具有相同值的颜色定义。

在具有该唯一 ID 的 RelativeLayout 上,有时我会像这样设置新颜色:

myLayout.setBackgroundColor(getResources().getColor(R.color.popup_background_red));

popup_background_red 的值为 #E3463D,这很好用。

问题来了。在某些设备上(例如 Samsung Galaxy S3 和旧的 Google Nexus S,可能还有其他设备),其他视图中的一些其他布局将背景设置为具有值 #EDEDED 的颜色定义,现在以 #E3463D 颜色显示,尽管从未在这些布局上调用 setBackgroundColor,并且它们是完全不同的布局,具有自己独特的 ID,并且存在于完全不同的视图中。更糟糕的是,布局受到影响似乎是随机的(即使在同一设备上也不总是相同)并且只有一些设备有这个问题。

有人知道这里发生了什么吗?我可以做些什么来防止这种情况吗?

谢谢
索伦

我 99% 确定这是由于 resource caching。如果您在最新版本的 SDK 中包含的 View 版本上检查 setBackgroundColor(int color) 的代码:

public void setBackgroundColor(@ColorInt int color) {
    if (mBackground instanceof ColorDrawable) {
        ((ColorDrawable) mBackground.mutate()).setColor(color);
        computeOpaqueFlags();
        mBackgroundResource = 0;
    } else {
        setBackground(new ColorDrawable(color));
    }
}

您会注意到 .mutate()。我怀疑你看到这个问题的测试设备有不同版本的视图,不包括对 mutate().

的调用

因此,正如我在对该问题的评论中提到的,您可以为此视图创建一个 new ColorDrawable(),以确保使用 popup_background 的所有其他视图不会全部更改同时(由于 shared constant state)。

尝试使用 setBackgoundDrawable(new ColorDrawable(color))) 而不是 setBackground(color)

这里解释了为什么你必须这样做: