Android视图背景意外更改

18

我正在开发一个有很多屏幕的应用程序。 大多数屏幕顶部都有一个带背景颜色的视图。

我经常使用 view.setBackgroundColor(color) 改变颜色。

这里出现了奇怪的事情:有时在将一个视图的颜色设置为 #f14fb7 后,当在应用程序中导航时,其他视图的背景也被设置为该颜色,而我并不想要这样。 甚至有时会发生在我没有为其设置 id 的视图上,因此无法调用 setBackgroundColor 对这些视图进行设置背景色。

这种情况很少发生,并且不一致。

当我杀死应用程序并重新启动它时,一切工作正常。

我的唯一猜测是某种内存泄漏,但我希望有一个更简单的解释。

有人能想到这种情况发生的原因吗?

*这在我的 Galaxy S3 上发生。


2
我们需要看一些代码才能理解你是如何布置屏幕和视图的。 - Szymon Rozga
也许你的最外层背景有颜色,然后你在上面放置其他布局,背景是透明的或者其他什么? - Nezam
我没有可以发布的代码,因为这种情况发生在整个应用程序中。 Nezam,不是那样的...95%的时间这个问题不会发生。 但设置背景的代码是view.setBackgroundColor(color)...没什么特别的。 奇怪的是它会影响其他与该特定屏幕无关的屏幕...这就是我怀疑它是内存泄漏的原因。 - dors
如果你需要安慰的话,我也遇到了这个问题。在我的Galaxy S3上,应用程序中的随机视图都会突然变为同一种颜色,但它们之间没有任何联系,我也无法弄清原因。 - jmhend
3个回答

15

没有代码的话很难说清楚...但我猜你在多个视图上重复使用了同一个ColorDrawable,如果你看一下View.setBackgroundColor()的源代码:

public void setBackgroundColor(int color) {
    if (mBGDrawable instanceof ColorDrawable) {
        ((ColorDrawable) mBGDrawable).setColor(color);
    } else {
        setBackgroundDrawable(new ColorDrawable(color));
    }
}

您可以看到它改变了ColorDrawable的颜色,而不是每次创建一个新的。我相信这就是您出现奇怪行为的原因。 编辑 当您在xml中使用android:background设置初始背景颜色时,根据Android文档,会执行以下操作:
将背景设置为给定资源。该资源应引用一个Drawable对象。
根据我的理解,它将在填充期间设置字段View.mBGDrawable。我建议您使用View.setBackgoundDrawable(new ColorDrawable(the_color_int_code)))代替setBackgroung(the_color_int_code)。这应该可以解决您的问题。

验证我的建议是否正确:在调试时,请注意显示相同背景的两个视图的“mBGDrawable”引用。如果这是相同的引用,则我的建议是正确的。 - ben75
我在我的应用程序的多个元素中遇到了完全相同的问题(但至少我很高兴知道我不是唯一面临这个问题的人)。 我发现两个元素(特别是)位于不同的屏幕上,它们正在更改为相同的颜色,但资源名称不同,R.java文件上的值也不同……我没有任何想法:( 我正在使用Google Apis并在ICS(4.0.3)上进行测试。 - Paulina D.
@ben75 我已经将所有 setBackgroundColor(COLOR) 的调用替换为 setBackground(new ColorDrawable(COLOR)),但我不确定它是否有效,因为我无法稳定地重现错误。 如果颜色更改在一周内没有问题,我会告诉你的。 顺便说一下,客户的手机是 Galaxy S III mini (GT-I8190L)。 - SparK
@ben75 我可以确认你的解决方案适用于我的情况,而且这是100%可复现的。 - Catalin Iacob
1
@KarthikaPB 这个问题只有在运行时改变其中一个背景时才会出现。此时,您可以创建一个新的ColorDrawable(int color)并设置它,或者如果您正在对背景应用过滤器,请在应用过滤器之前记得调用.mutate() 方法。 - ataulm
显示剩余7条评论

6

如果您在xml中设置了视图的颜色,通常会发生这种情况,例如:

android:background="@color/cyan" 

现在,它在该视图的类中内部创建了一个新的ColorDrawable - 让我们称其为conceptual_drawable_cyan。当同一视图通过编程方式被分配不同的颜色时:

view.setBackgroundColor(newColor);

在内部,这个视图不会创建一个不同的可绘制对象,而是将newColor设置为drawable_cyan。因此,从此时开始,如果您在任何地方使用

android:background="@color/cyan" 

视图实际上会使用 conceptual_drawable_cyannewColor
解决方案:
不要使用 setBackgroundColor 来以编程方式设置颜色,改用:
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        view.setBackground(new ColorDrawable(newColor));
    } else {
        view.setBackgroundDrawable(new ColorDrawable(newColor));
    }

1
在“values”文件夹下创建“colors.xml”文件。例如:
<?xml version="1.0" encoding="utf-8"?>
<resources><color name="pink">#f14fb7</color></resources>

使用 view.setBackgroundResource(R.color.pink);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接