Android getResources().getDrawable() 在API 22中已被弃用

849

随着新的安卓API 22,getResources().getDrawable() 现在已经被弃用。

现在最好的方法是仅使用 getDrawable() 来获取Drawable对象。

发生了什么变化?


你能具体说明你的问题吗?Resources类的方法getDrawable(int id)被弃用了。现在你应该使用带有新主题参数的方法getDrawable(int id,Resources.Theme theme) - code monkey
2
ContextCompat.getDrawable(context, R.color.color_name) - Ashokchakravarthi Nagarajan
您可以查看我的博客文章,了解更详细的说明,为什么Resources#getDrawable(int)Resources#getColor(int)都已被弃用。 - Alex Lockwood
1
Google 应该为每个已弃用的函数提供快速修复。我在这里发了一篇帖子:https://code.google.com/p/android/issues/detail?id=219495 - android developer
16个回答

1300

针对这种淘汰的情况,你有几种选项可以选择正确(并且具有未来证明)的方式进行处理,具体取决于您加载哪种类型的可绘制对象:


A) 具备主题属性的可绘制对象

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

根据您的Activity主题指示,您将获得一个已设置样式的Drawable。这很可能是您所需要的。


B) 没有主题属性的可绘制对象

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

你将以旧的方式获取未样式化的可绘制对象。请注意:ResourcesCompat.getDrawable()没有过时!


额外)另一个主题获取带有主题属性的可绘制对象。

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

我的应用程序在使用建议B时崩溃了。它不喜欢调用Drawable originalIcon = ResourcesCompat.getDrawable(ctxt.getResources(), iconResId, null); - FractalBob
我这样声明它: 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); }并像这样调用它:Utility.setImageButtonEnabled(getContext(), false, back, R.drawable.arrow_left); - FractalBob
更准确地说,崩溃似乎是因为我的图标是矢量可绘制的。 - FractalBob
1
xamarin版本: ResourcesCompat.GetDrawable(Resources, Resource.Drawable.name, null); - Brian
在适配器中使用类似这样的代码 - ResourcesCompat.getDrawable(viewGroup.getContext().getResources(), R.drawable.touch_feedback, null); - Divyanshu Kumar
显示剩余2条评论

759

编辑:请参考我的博客文章,获取更完整的解释。


您应使用支持库中的以下代码:

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

使用这种方法相当于调用:

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

从API 21开始,您应该使用getDrawable(int, Theme)方法来替代getDrawable(int),因为它允许您获取与给定屏幕密度/主题相关联的特定资源ID的可绘制对象。调用已弃用的getDrawable(int)方法等同于调用getDrawable(int, null)


8
我认为OP也指的是Context类的getDrawable(int id)方法。这与getResources().getDrawable(id, getTheme())相同,也使用了新的API。 - code monkey
9
根据文件说明,要使用getDrawable(int, Resources.Theme)需要最低API级别为21。 - Prince
@Prince 这个方法是在API 21中添加的,但直到API 22才被弃用。 :) - Alex Lockwood
Android文档还建议使用Context :: getDrawable(int)方法,但由于它仅在API 21中引入,因此ContextCompat似乎是最佳选择。 - goRGon
这个答案在API 21之前的版本中不能处理.svg文件。这个库存在一个bug。 - Jorge Rodríguez
当从Fragment中调用建议时,建议会失败: Drawable originalIcon = ContextCompat.getDrawable(getContext(), R.drawable.arrow_left); - FractalBob

150

将此行替换:

getResources().getDrawable(R.drawable.your_drawable)

ResourcesCompat.getDrawable(getResources(), R.drawable.your_drawable, null) 代替。

编辑

ResourcesCompat现在也已弃用。您可以使用以下方法:

ContextCompat.getDrawable(this, R.drawable.your_drawable)(这里的this是上下文)

有关更多详细信息,请访问此链接:ContextCompat


2
这个现在也已经过时了:https://plus.google.com/+BenjaminWeiss/posts/M1dYFaobyBM - Xyaren
请查看此链接:https://developer.android.com/reference/android/support/v4/content/ContextCompat.html#getDrawable(android.content.Context, int) - vincent091
2
链接中并没有说明ResourcesCompat已经被弃用。它应该可以正常工作。 - Jacob R
如果我想在单击存储在drawable中的列表项时将图像输入到列表视图中,应该在“您的drawable”中编写什么? - 0x0001

29

getResources().getDrawable()在API级别22中已被弃用。现在我们必须添加主题:

getDrawable(int id, Resources.Theme theme)(在API级别21中添加)

这是一个例子:

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

这是一个验证后续版本的示例:

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 是 API 21,所以这个判断应该是 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) 或者 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP)?算了,从下面的话来看,“该方法在 API 21 中添加,但直到 API 22 才被弃用。:)” - Mark Cramer

12

试一试

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

9

getDrawable(int drawable)在API级别22中已被弃用。 有关详细信息,请参阅此link

现在要解决这个问题,我们必须传递一个新的构造函数和id,如下所示:

getDrawable(int id, Resources.Theme theme)

解决方案可以这样做:

在Java中:

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

或者

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

在Kotlin中:
rel_week.background=ContextCompat.getDrawable(this, R.color.colorWhite)
 or,
rel_week.background=ContextCompat.getDrawable(requireContext(), R.color.colorWhite)
)

或者

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

希望这能对你有所帮助。谢谢。

值得一提的是,getDrawable(DrawableRes int id, Theme theme) 如果资源未找到,则可能会抛出异常,而getDrawable(Context context, int id) 是可空的,因此在Kotlin中必须使用Drawable?返回。 - Pitos
这个格式非常糟糕,而且 Kotlin 代码无法编译。 - J. Doe
@J.Doe,是的,这可能是旧代码。我会更新新答案。 - Rahul Kushwaha

8
在 Kotlin 中,你可以使用扩展函数。
fun Context.getMyDrawable(id : Int) : Drawable?{

    return  ContextCompat.getDrawable(this, id)
}

然后使用类似如下的方式:

context.getMyDrawable(R.drawable.my_icon)

3
您可以使用

标签


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

对我来说是有效的


使用应用程序上下文加载矢量图在Lollipop之前的版本上会崩溃。有什么解决方法吗? - muthuraj
1
@muthuraj,我不记得我的代码在棒棒糖环境下的测试了,但是你可以尝试使用getActivity()或者getResources(),然后看一下这些方法是否适用于你的代码? - Dasser Basyouni
我正在使用MVVM模式,需要在没有活动上下文的ViewModel中填充可绘制对象。它只有应用程序上下文。这就是我的问题所在。 - muthuraj

1
如果您的目标SDK大于21(棒棒糖或5.0),请使用:
context.getDrawable(R.drawable.your_drawable_name)

查看文档


1

这只是一个关于如何解决数组问题以加载listView的示例,希望能有所帮助。

 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)));

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