Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android View background changes unexpectedly

I'm building an app that has plenty of screens. most of the screens have a View at the top with a background color.

I often change that color using view.setBackgroundColor(color)

Here comes the weird thing: sometimes after setting the color of one view, say to #f14fb7 , when navigating in the app, other views' backgrounds are set to that color without me wanting them to. It sometimes even happens to views I had not set an id for, so there is no way setBackgroundColor was called on those views.

This happens rarely and is not consistant to any flow I tried.

When I kill the app and restart it, everything works as it should.

My only guess is some king of memory leak, but I hope there is a simpler explanation.

Can anyone think of some reason for this to happen?

*It happens on my Galaxy S3.

like image 354
dors Avatar asked Feb 14 '13 12:02

dors


3 Answers

Without the code it's not easy... but I guess you are reusing the same ColorDrawable on multiple views and if you take a look at View.setBackgroundColor() source code :

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

You can see that it change the color of the ColorDrawable and don't create a new one each time. I'm pretty sure this is why you have this strange behavior.

EDIT

When you set the initial background color in xml with android:background you are doing this (according android doc):

Set the background to a given resource. The resource should refer to a Drawable object

According my understanding it will set the field View.mBGDrawable during the inflate. I suggest you to use View.setBackgoundDrawable(new ColorDrawable(the_color_int_code))) instead of setBackgroung(the_color_int_code). It should solve your issue.

like image 145
ben75 Avatar answered Dec 02 '22 16:12

ben75


This usually happens if you have a view whose color is set in xml ex:

android:background="@color/cyan" 

Now this internally creates a new ColorDrawable - lets call it conceptual_drawable_cyan inside that view's class. Now when same view is assigned a different color programmatically using:

view.setBackgroundColor(newColor);

Internally this view instead of creating a different drawable it sets this newColor to drawable_cyan. Hence from this point onwards if you anywhere use

android:background="@color/cyan" 

the view would actually use conceptual_drawable_cyan with newColor.

Solution:

Instead of using setBackgroundColor to set color programmatically, use:

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        view.setBackground(new ColorDrawable(newColor));
    } else {
        view.setBackgroundDrawable(new ColorDrawable(newColor));
    }
like image 38
Aalap Avatar answered Dec 02 '22 17:12

Aalap


Create the "colors.xml" file under the "values" folder. Example:

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="pink">#f14fb7</color></resources>

Use view.setBackgroundResource(R.color.pink);

like image 39
Andrea Motto Avatar answered Dec 02 '22 18:12

Andrea Motto