相信大家在开发中,经常会动态改变控件的颜色,但对于改变drawable下背景的背景色该如何修改呢,修改后又会带来什么问题呢,请大家带着疑问细细看来:
先上代码,在drawable下修改背景:
GradientDrawable p = (GradientDrawable) tv_check_insurance_vin.getBackground().mutate();
p.setColor(Color.parseColor("#3D5B96"));
代码很简单,就两行便解决了我们的问题,但不知道你会不会发现这么修改后,会导致其他界面这个drawable的颜色也会跟着改变,这让我们有的找不到原因,先不要着急,解决办法很简单:
修改代码:
GradientDrawable p = (GradientDrawable) tv_check_insurance_vin.getBackground().mutate();
p.setColor(Color.parseColor("#3D5B96"));
同理 一个控件改变背景色也可以这么操作 tv.getBackground().mutate().setAlpha(0);
当然也有其他方案,只要在ondestroy改变回你自己颜色就可以了。
问题解决了,那我们来分析下造成这样的原因吧:
Drawables允许你不需要继承就可以很容易的定制widgets渲染。事实是,android的应用程序和widgets是使用该drawable对象的,在android的核心框架
中大约有700个drwables被使用。。正式以为他是如此广泛的被使用,Android对它进行了优化。例如,每一次你创建一个按钮时,一个新的drawable就会
被装载。这就意味着应用程序中所有的使用不同drawablesd对象实现不同背景的按钮,所有的drawables对象公用一个公用的状态,我们成“constant
state”,这个状态的内如根据你使用的不同drawables对象而不同,但是它通常包括一个资源所有的属性。以按钮为例,常态包括一个位图。如此一所
有按钮就可以共享一张位图。这将会节省很多的资源。
下面的图介绍了你设置一张图给两个不同View作为背景的创建过程。正如你所看到的那样,两个drawables被创建,但是共享公共的部分也就是同一张位图。
这种状态分享特点极大避免了浪费内存,但是当你试图去修改drawable的属性时它会导致一些问题。导致背景色错落。
这种结果能够用上面的“常态”来解释。因为我们从一个list item中获取一个drawable对象时,constant state是一样的,对BitmapDrawable来说,
透明值就是一个常态,因此,改变一个drawable对象实例的透明值来说,会改变所有其他对象的透明值,更糟糕是,这种问题在1.1和1.0的是不好解决的。
在1.5或者更好的设备上通过mutate()方法是很容易解决上述问题。当你对一个drawable对象调用这个方法时,drawable对象就会被复制而不会印象其他对象。
记住bitmap对象依旧是被重用的,即使是实用mutate(),下面这幅图说明调用mutate()对象之后情况
只要调用了链式上的mutate方法,问题也就解决了。