ChatGPT解决这个技术问题 Extra ChatGPT

Android getResources().getDrawable() deprecated API 22

With new android API 22 getResources().getDrawable() is now deprecated. Now the best approach is to use only getDrawable().

What changed?

Could you specify your question? It is right that the method getDrawable (int id) of the class Resources is deprecated. You should now use the method getDrawable (int id, Resources.Theme theme) with the new theme parameter.
ContextCompat.getDrawable(context, R.color.color_name)
You can check out my blog post on this subject for a more thorough explanation about why both Resources#getDrawable(int) and Resources#getColor(int) were deprecated.
Google should put quick-fixes for each deprecated function. I made a post about it here: code.google.com/p/android/issues/detail?id=219495

A
Alex Lockwood

You have some options to handle this deprecation the right (and future proof) way, depending on which kind of drawable you are loading:

A) drawables with theme attributes

ContextCompat.getDrawable(getActivity(), R.drawable.name);

You'll obtain a styled Drawable as your Activity theme instructs. This is probably what you need.

B) drawables without theme attributes

ResourcesCompat.getDrawable(getResources(), R.drawable.name, null);

You'll get your unstyled drawable the old way. Please note: ResourcesCompat.getDrawable() is not deprecated!

EXTRA) drawables with theme attributes from another theme

ResourcesCompat.getDrawable(getResources(), R.drawable.name, anotherTheme);

My app crashes using suggestion B. It doesn't like the call Drawable originalIcon = ResourcesCompat.getDrawable(ctxt.getResources(), iconResId, null);
I declare it this way: public static void setImageButtonEnabled(Context ctxt, boolean enabled, ImageButton item, int iconResId) { item.setEnabled(enabled); Drawable originalIcon = ResourcesCompat.getDrawable(ctxt.getResources(), iconResId, null); Drawable icon = enabled ? originalIcon : convertDrawableToGrayScale(originalIcon); item.setImageDrawable(icon); } and call it like this: Utility.setImageButtonEnabled(getContext(), false, back, R.drawable.arrow_left);
More precisely, the crash seems to be happening because my icon is a Vector drawable.
xamarin version: ResourcesCompat.GetDrawable(Resources, Resource.Drawable.name, null);
I add one further word to you,ContextCompat.getColor(context,color) also can help you...
A
Alex Lockwood

Edit: see my blog post on the subject for a more complete explanation

You should use the following code from the support library instead:

ContextCompat.getDrawable(context, R.drawable.***)

Using this method is equivalent to calling:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    return resources.getDrawable(id, context.getTheme());
} else {
    return resources.getDrawable(id);
}

As of API 21, you should use the getDrawable(int, Theme) method instead of getDrawable(int), as it allows you to fetch a drawable object associated with a particular resource ID for the given screen density/theme. Calling the deprecated getDrawable(int) method is equivalent to calling getDrawable(int, null).


I think that the OP also refers to the getDrawable (int id) method of the Context class. This is the same as getResources().getDrawable(id, getTheme()); and also uses the new API.
According to documentation, min API level 21 is required to use getDrawable(int, Resources.Theme).
@Prince The method was added in API 21 but it wasn't deprecated until API 22. :)
Android doc also recommends using Context::getDrawable(int) method but since it was introduced only in API 21 seems that ContextCompat is the best choice.
This answer does not work with .svg files, in versions older than API 21. There is a bug in the library.
N
Nagaraju Gajula

Replace this line : getResources().getDrawable(R.drawable.your_drawable)

with ResourcesCompat.getDrawable(getResources(), R.drawable.your_drawable, null)

EDIT

ResourcesCompat is also deprecated now. But you can use this:

ContextCompat.getDrawable(this, R.drawable.your_drawable) (Here this is the context)

for more details follow this link: ContextCompat


It doesn't say in link that ResourcesCompat is deprecated. It should work fine.
what to write in "your drawable" if i want to input images to a list view on clicking list items stored in drawable
J
Jorgesys

getResources().getDrawable() was deprecated in API level 22. Now we must add the theme:

getDrawable (int id, Resources.Theme theme) (Added in API level 21)

This is an example:

myImgView.setImageDrawable(getResources().getDrawable(R.drawable.myimage, getApplicationContext().getTheme()));

This is an example how to validate for later versions:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //>= API 21
     myImgView.setImageDrawable(getResources().getDrawable(R.drawable.myimage, getApplicationContext().getTheme()));
   } else { 
     myImgView.setImageDrawable(getResources().getDrawable(R.drawable.myimage));
}

Build.VERSION_CODES.LOLLIPOP is API 21, so shouldn't this be if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) or if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP)? Never mind. From below "The method was added in API 21 but it wasn't deprecated until API 22. :)"
D
Deepak Ror

In Kotlin you can use extension

fun Context.getMyDrawable(id : Int) : Drawable?{

    return  ContextCompat.getDrawable(this, id)
}

then use like

context.getMyDrawable(R.drawable.my_icon)

A
Aalishan Ansari

Try this

ContextCompat.getDrawable(getActivity(), R.drawable.drawable_resource_name);

R
Rahul Kushwaha

getDrawable(int drawable) is deprecated in API level 22. For reference see this link.

Now to resolve this problem we have to pass a new constructer along with id like as :-

getDrawable(int id, Resources.Theme theme)

For Solutions Do like this:-

In Java:-

ContextCompat.getDrawable(getActivity(), R.drawable.name);   

or

 imgProfile.setImageDrawable(getResources().getDrawable(R.drawable.img_prof, getApplicationContext().getTheme()));

In Kotlin :-

rel_week.background=ContextCompat.getDrawable(this.requireContext(), R.color.colorWhite)

or

 rel_day.background=resources.getDrawable(R.drawable.ic_home, context?.theme)

Hope this will help you.Thanks.


It is worth mentioning, that getDrawable(DrawableRes int id, Theme theme) can throw an exception if the resource is not found while, getDrawable(Context context, int id) is nullable, so it has to be returned with Drawable? in Kotlin.
D
Dasser Basyouni

You can use

ContextCompat.getDrawable(getApplicationContext(),R.drawable.example);

that's work for me


Using application context to load vector drawable crashes on pre lollipop. Any fix for this?
@muthuraj I don't remember my testing for the code with lollipop case, but you can try getActivity() or getResources() instead then, does that goes well with your code ?
I'm using MVVM pattern and I need to inflate drawables inside ViewModels which don't have activity context. It only has application context. That's what my issue is.
J
Jay

Just an example of how I fixed the problem in an array to load a listView, hope it helps.

 mItems = new ArrayList<ListViewItem>();
//    Resources resources = getResources();

//    mItems.add(new ListViewItem(resources.getDrawable(R.drawable.az_lgo), getString(R.string.st_az), getString(R.string.all_nums)));
//    mItems.add(new ListViewItem(resources.getDrawable(R.drawable.ca_lgo), getString(R.string.st_ca), getString(R.string.all_nums)));
//    mItems.add(new ListViewItem(resources.getDrawable(R.drawable.co_lgo), getString(R.string.st_co), getString(R.string.all_nums)));
    mItems.add(new ListViewItem(ResourcesCompat.getDrawable(getResources(), R.drawable.az_lgo, null), getString(R.string.st_az), getString(R.string.all_nums)));
    mItems.add(new ListViewItem(ResourcesCompat.getDrawable(getResources(), R.drawable.ca_lgo, null), getString(R.string.st_ca), getString(R.string.all_nums)));
    mItems.add(new ListViewItem(ResourcesCompat.getDrawable(getResources(), R.drawable.co_lgo, null), getString(R.string.st_co), getString(R.string.all_nums)));

D
Donald Duck

Try this:

public static List<ProductActivity> getCatalog(Resources res){
    if(catalog == null) {
        catalog.add(new Product("Dead or Alive", res
                .getDrawable(R.drawable.product_salmon),
                "Dead or Alive by Tom Clancy with Grant Blackwood", 29.99));
        catalog.add(new Product("Switch", res
                .getDrawable(R.drawable.switchbook),
                "Switch by Chip Heath and Dan Heath", 24.99));
        catalog.add(new Product("Watchmen", res
                .getDrawable(R.drawable.watchmen),
                "Watchmen by Alan Moore and Dave Gibbons", 14.99));
    }
}

While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.
A
Adeel Ahmad

If you are targeting SDK > 21 (lollipop or 5.0) use

context.getDrawable(R.drawable.your_drawable_name)

See docs


C
ColdFire

en api level 14

marker.setIcon(ResourcesCompat.getDrawable(getResources(), R.drawable.miubicacion, null));

You should provide a bit more context around your answer.
F
Farid Haq

Now you need to implement like this

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //>= API 21
        //
    } else {
        //
    }

Following single line of code is enough, everything will take care by ContextCompat.getDrawable

ContextCompat.getDrawable(this, R.drawable.your_drawable_file)

S
Stamatis Stiliats

For some who still got this issue to solve even after applying the suggestion of this thread(i used to be one like that) add this line on your Application class, onCreate() method

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)

As suggested here and here sometimes this is required to access vectors from resources especially when you're dealing with menu items, etc


K
Khalid Lakhani

In case you need drawable from other app targeting SDK 23 and up

PackageManager manager = getApplicationContext().getPackageManager();
Resources resources = null;
try {
    resources = manager.getResourcesForApplication("com.anyapp");
    } 
catch (PackageManager.NameNotFoundException e) {
   e.printStackTrace();
   }
assert resources != null;
Drawable notiIcon = ResourcesCompat.getDrawable(resources, current.iconId/* drawable resource id */, null);

C
ColdFire

Build.VERSION_CODES.LOLLIPOP should now be changed to BuildVersionCodes.Lollipop i.e:

if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop) {
    this.Control.Background = this.Resources.GetDrawable(Resource.Drawable.AddBorder, Context.Theme);
} else {
    this.Control.Background = this.Resources.GetDrawable(Resource.Drawable.AddBorder);
}

Isn't BuildVersionCodes a class specific to Xamarin?