ChatGPT解决这个技术问题 Extra ChatGPT

setBackground vs setBackgroundDrawable (Android)

I want to set background drawable of a view. There are two methods for this (as far as I see): setBackground and setBackgroundDrawable.

When I use setBackground, it says it has been added in API level 16 but my project's min SDK version is 7. I assume it's not going to work on anything below 16, am I right? But when I use setBackgroundDrawable, it says it's deprecated.

What am I supposed to use?

Use: image.setImageResource(R.drawable.icon_dot1);

W
Warpzit

It's deprecated but it still works so you could just use it. But if you want to be completly correct, just for the completeness of it... You'd do something like following:

int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
    setBackgroundDrawable();
} else {
    setBackground();
}

For this to work you need to set buildTarget api 16 and min build to 7 or something similar.


It still complains about setBackgroundDrawable being deprecated. Do I really have to suppresswarnings just because Google wanted to change the method name?
@santirivera92 Yes you have, alternatively you can create 2 projects 1 targeting before it was an issue and 1 after. Does that sound like an easy option? (Actually sometimes it does, so many fixes in ICS)
I set android:minSdkVersion="7" android:targetSdkVersion="17", however setBackground() comes out as error: Call requires API level 16 (current min is 7)
It prevented me from compiling. I put the problematic code in its own function and disabled lint only for that function like this. @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @SuppressWarnings("deprecation") private static void setBg(RelativeLayout layout, BitmapDrawable TileMe) { if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) { layout.setBackgroundDrawable(TileMe); } else { layout.setBackground(TileMe); } }
@Snicolas Yes, the IDE or Android should be able to do this kind of logic for us.
A
Alex Lockwood

You can use setBackgroundResource() instead which is in API level 1.


...but only if you got a ressource id and not a custom drawable class you created!
there is no method to retrieve the ID of a drawable you have a reference on ?
setBackgroundResource() is not alternative to setBackgroundDrawable(); or setBackground();. Not related at all, the first one to add resource drawable and the others to add CUSTOM drawable.
What if I have to set background repeatedly, say in listview? setBackgroundResource(int) accepts resource id, therefore it has to inflate the view each time in order to set the background. I do not want such behaviour, assuming I already have inflated Drawable. Am I missing something?
what if i do only have the drawable !?
C
Community

seems that currently there is no difference between the 2 functions, as shown on the source code (credit to this post) :

public void setBackground(Drawable background) {
    //noinspection deprecation
    setBackgroundDrawable(background);
}

@Deprecated
public void setBackgroundDrawable(Drawable background) { ... }

so it's just a naming decision, similar to the one with fill-parent vs match-parent .


great! thanks. Silly that a warning is generated for something as lame as a function rename.
@M.kazemAkhgary It's not the first time they deprecate something only for name changing. They had "fill_parent" being changed to "match_parent" for layout params values. Both are exactly the same thing, pointing to the same value..
J
Jose De Gouveia

i know this is an old question but i have a similar situation ,and my solution was

button.setBackgroundResource( R.drawable.ic_button );
Drawable d = button.getBackground();

and then you can play with the "Drawable", applying color filters, etc


This only works if the original image is coming from a resource.
This doesn't even answer the OP's question.
k
krawa

Use ViewCompat.setBackground(view, background);


p
ponnex

you could use setBackgroundResource() instead i.e. relativeLayout.setBackgroundResource(R.drawable.back);

this works for me.


A
Aksel Willgert

Using Android studio 1.5.1 i got the following warnings:

Call requires API level 16 (current min is 9): android.view.View#setBackground

and the complaints about deprecation

'setBackgroundDrawable(android.graphics.drawable.Drawable)' is deprecated

Using this format, i got rid of both:

    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
        //noinspection deprecation
        layout.setBackgroundDrawable(drawable);
    } else {
        layout.setBackground(drawable);
    }

G
Geraldo Neto

Now you can use either of those options. And it is going to work in any case. Your color can be a HEX code, like this:

myView.setBackgroundResource(ContextCompat.getColor(context, Color.parseColor("#FFFFFF")));

A color resource, like this:

myView.setBackgroundResource(ContextCompat.getColor(context,R.color.blue_background));

Or a custom xml resource, like so:

myView.setBackgroundResource(R.drawable.my_custom_background);

Hope it helps!


u
user0987

This works for me: View view is your editText, spinner...etc. And int drawable is your drawable route example (R.drawable.yourDrawable)

 public void verifyDrawable (View view, int drawable){

        int sdk = Build.VERSION.SDK_INT;

        if(sdk < Build.VERSION_CODES.JELLY_BEAN) {
            view.setBackgroundDrawable(
                    ContextCompat.getDrawable(getContext(),drawable));
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            view.setBackground(getResources().getDrawable(drawable));
        }    
    }

b
baburaoS

Use setBackgroundResource(R.drawable.xml/png)


J
Jens-Joris Decorte

I also had this problem, but I made a workaround using a ImageView.

Try using a RelativeLayout and add a ImageView inside it (width and height: fill_parent, scaleType: center).

Also make sure the imageview is the first element inside the RelativeLayout, so it will act as background.


Actually it should have been no more than an if clause. See the correct answer.
T
Tobrun

You can also do this:

try {
     myView.getClass().getMethod(android.os.Build.VERSION.SDK_INT >= 16 ? "setBackground" : "setBackgroundDrawable", Drawable.class).invoke(myView, myBackgroundDrawable);
} catch (Exception ex) {
     // do nothing
}

EDIT: Just as pointed out by @BlazejCzapp it is preferable to avoid using reflection if you can manage to solve the problem without it. I had a use case where I was unable to solve without reflection but that is not case above. For more information please take a look at http://docs.oracle.com/javase/tutorial/reflect/index.html


@BlazejCzapp LOL, but it DOES answer the question, so it shouldn't be downvoted without an explanation. When you tell a child to not do something without telling why they will do that ;)
I don't want to go off topic, but here are some reasons: 1. Java is a statically typed language - make use the compiler; 2. This is just an if-statement in disguise (it's obfuscating the true logic); 3. It's bringing out a cannon to kill a mosquito - this code is using some serious artillery to solve a trivial problem; Hope that justifies it somewhat
Thanks @BlazejCzapp, you are right, I had an use case here where it was necessary to do things like the code above but it shouldn't be used if there is a proper way to handle this.
This is dumb... there is absolutely no reason to use reflection to achieve this.
Yes tell someone who asked a simple question "What am I supposed to use?" start modifying the run-time.