在 Android 6.0 Marshmallow (API 23) 上不推荐使用 getColor(int id)

Posted

技术标签:

【中文标题】在 Android 6.0 Marshmallow (API 23) 上不推荐使用 getColor(int id)【英文标题】:getColor(int id) deprecated on Android 6.0 Marshmallow (API 23) 【发布时间】:2015-10-13 22:57:29 【问题描述】:

Resources.getColor(int id) 方法已被弃用。

@ColorInt
@Deprecated
public int getColor(@ColorRes int id) throws NotFoundException 
    return getColor(id, null);

我该怎么办?

【问题讨论】:

使用 ContextCompat.getColor(context, R.color.color_name) 用上面提到的这个方法:getColor(context, R.color.your_color);目前尚不清楚如何获得“上下文”。仅在我的情况下,android studio 3.2 中将上下文放在那里是行不通的。我发现这对我有用。 .setTextColor(Color.RED). 【参考方案1】:

从 Android 支持库 23 开始, ContextCompat 中添加了新的 getColor() 方法。

来自官方JavaDoc的描述:

返回与特定资源 ID 关联的颜色

从 M 开始,返回的颜色将为指定的 Context 的主题设置样式。

所以,打电话

ContextCompat.getColor(context, R.color.your_color);

您可以查看ContextCompat.getColor()source code on GitHub。

【讨论】:

这看起来像是解决方案,但是当我们收到错误“应该在这里传递解析的颜色而不是资源ID”时我们应该怎么做?据我所知,这可能是因为 Lint 不识别支持库的新 API,所以也许只是添加注释 @SuppressWarnings("ResourceAsColor") 是要走的路?不过我不太喜欢。 嗨@Stan,您能否提供代码 sn-p 以及触发“ResourceAsColor”Lint 的方法调用? @MonicaLabbao 哦...对不起,我误解了您的评论! :) ContextCompatApi23 this mark error supossed you reference ContextCompat 我不明白“主题”有什么用。有例子吗?【参考方案2】:

tl;博士:

ContextCompat.getColor(context, R.color.my_color)

解释:

您需要使用 ContextCompat.getColor(),它是 Support V4 库的一部分(它适用于所有以前的 API)。

ContextCompat.getColor(context, R.color.my_color)

如果您还没有使用支持库,则需要将以下行添加到应用程序 build.gradle 内的 dependencies 数组中(注意:如果您已经使用了 appcompat(V7 ) 库):

compile 'com.android.support:support-v4:23.0.0' # or any version above

如果您关心主题,文档会指定:

从 M 开始,返回的颜色将被设置为指定的样式 上下文的主题

【讨论】:

这应该被选为正确答案。因为在 Android Docs 的给定链接中,它说“M开始,返回的颜色将为指定的上下文主题设置样式。 编译'com.android.support:appcompat-v7:23.0.1' @G O'Rilla 正如您在文档中看到的,ContextCompat 类来自 SupportV4。 AppcompatV7 也可以工作,因为它依赖于 SupportV4。正如他们在Support Library documentation、This library depends on the v4 Support Library. If you are using Ant or Eclipse, make sure you include the v4 Support Library as part of this library's classpath. 上所说的那样。因此,不要将AppcompatV7 放在答案中是有道理的。 感谢@Melvin,这是我使用的示例: int colorTwitterBlue = ContextCompat.getColor(this, R.color.color_twitter_blue); composeTweetAlertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(colorTwitterBlue); composeTweetAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(colorTwitterBlue); @Melvin。这到底是什么意思'颜色将被设置为指定的上下文主题'。听起来可以根据主题为相同的颜色 id 定义不同的颜色。这到底是怎么做的?【参考方案3】:

我不想只为 getColor 包含支持库,所以我使用类似

public static int getColorWrapper(Context context, int id) 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
        return context.getColor(id);
     else 
        //noinspection deprecation
        return context.getResources().getColor(id);
    

我猜代码应该可以正常工作,并且已弃用的 getColor 不能从 API

这就是我在 Kotlin 中使用的:

/**
 * Returns a color associated with a particular resource ID.
 *
 * Wrapper around the deprecated [Resources.getColor][android.content.res.Resources.getColor].
 */
@Suppress("DEPRECATION")
@ColorInt
fun getColorHelper(context: Context, @ColorRes id: Int) =
    if (Build.VERSION.SDK_INT >= 23) context.getColor(id) else context.resources.getColor(id);

【讨论】:

看源码,支持库就是这么干的。我的目标 API >= 21 所以我不想为这几行包含一个完整的 jar。请注意,您可以通过在已弃用的调用上方添加“//noinspection deprecation”来抑制 Android Studio 中的警告。并使用 Activity 上下文,而不是 Application 上下文,否则您可能会丢失主题信息。 这应该是正确的答案,虽然支持库可能是更多面向未来的选择,但我同意如果这是您包含支持库的唯一原因,您最好包含这几行.【参考方案4】:

在 Android Marshmallow 中,许多方法已被弃用。

例如,获取颜色使用

ContextCompat.getColor(context, R.color.color_name);

也可以获得可绘制的使用

ContextCompat.getDrawable(context, R.drawable.drawble_name);

【讨论】:

变量上下文从何而来?我必须初始化它吗?我无法让它工作。对我来说,Androind 似乎还有很长的路要走。让我大吃一惊的是,我多么努力地从 xml 资源中获取 f 颜色!哇【参考方案5】:

致所有 Kotlin 用户:

context?.let 
    val color = ContextCompat.getColor(it, R.color.colorPrimary)
    // ...

【讨论】:

其实应该是val color = ContextCompat.getColor(context, R.color.colorPrimary)。变量“it”可以是任何东西,但它必须是 Context it 在这种情况下是context,因为我使用context?.let 来检查context 是否不为空。函数getColor() 只接受非空上下文。在此处阅读有关let 以及如何使用它的更多信息:kotlinlang.org/docs/reference/scope-functions.html#let【参考方案6】:

在 Kotlin 中,您可以这样做:

ContextCompat.getColor(requireContext(), R.color.stage_hls_fallback_snackbar)

如果 requireContext() 可以从你调用函数的地方访问。我在尝试时遇到错误

ContextCompat.getColor(context, R.color.stage_hls_fallback_snackbar)

【讨论】:

【参考方案7】:

在活动中使用了 ContextCompat

ContextCompat.getColor(context, R.color.color_name)

在 Adaper 中

private Context context;


context.getResources().getColor()

【讨论】:

【参考方案8】:

在 Kotlin 的 RecyclerView 中

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) 
    fun bind(t: YourObject, listener: OnItemClickListener.YourObjectListener) = with(itemView) 
        textViewcolor.setTextColor(ContextCompat.getColor(itemView.context, R.color.colorPrimary))
        textViewcolor.text = t.name
    

【讨论】:

【参考方案9】:

如果您的当前最小值。 API级别是23,你可以像我们使用getString()获取字符串资源一样简单地使用getColor()

//example
textView.setTextColor(getColor(R.color.green));
// if `Context` is not available, use with context.getColor()

您可以限制低于 23 的 API 级别:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
    textView.setTextColor(getColor(R.color.green));
 else 
    textView.setTextColor(getResources().getColor(R.color.green));

但为了简单起见,您可以像下面这样接受答案:

textView.setTextColor(ContextCompat.getColor(context, R.color.green))

来自Resources。

来自ContextCompat AndroidX。

来自ContextCompat Support

【讨论】:

【参考方案10】:

如果您不一定需要这些资源,请使用parseColor(String)Color.parseColor("#cc0066")

【讨论】:

【参考方案11】:

使用 Android 支持库中 ResourcesCompatgetColor(Resources, int, Theme) 方法。

int white = ResourcesCompat.getColor(getResources(), R.color.white, null);

我认为它比ContextCompatgetColor(Context, int) 更能反映你的问题,因为你问的是Resources。在 API 级别 23 之前,将不会应用主题并且方法会调用到 getColor(int),但您不会收到已弃用的警告。主题也可能是null

【讨论】:

如果您将 null 作为 Theme 参数传递,则返回的颜色将不会为当前主题设置样式。所以可能是不正确的。 @araks 与不推荐使用的调用不一样吗?毕竟,在这两种情况下,您都获得了 Resources 实例,而不是 Context。 @androiddeveloper 正是出于这个原因,他们已经弃用了该调用:以避免加载非主题资源。如果您传递 null 您使所有代码迁移工作无效,以解决此弃用问题,并使您面临加载非主题资源(主要是可绘制资源)的风险,而没有任何明确说明为什么它们没有按预期工作。因此,您应该始终从当前的 Activity/Fragment 中提供一个 Theme 实例,或者使用 ContextCompat.get* 方法。 @araks 你的意思是drawables有“?attr/”的情况?【参考方案12】:

我也很沮丧。我的需求非常简单。我想要的只是资源中的 ARGB 颜色,所以我写了一个简单的静态方法。

protected static int getARGBColor(Context c, int resId)
        throws Resources.NotFoundException 

    TypedValue color = new TypedValue();
    try 
        c.getResources().getValue(resId, color, true);
    
    catch (Resources.NotFoundException e) 
        throw(new Resources.NotFoundException(
                  String.format("Failed to find color for resourse id 0x%08x",
                                resId)));
    
    if (color.type != TYPE_INT_COLOR_ARGB8) 
        throw(new Resources.NotFoundException(
                  String.format(
                      "Resourse id 0x%08x is of type 0x%02d. Expected TYPE_INT_COLOR_ARGB8",
                      resId, color.type))
        );
    
    return color.data;

【讨论】:

【参考方案13】:

最好的等价物是使用 ContextCompat.getColorResourcesCompat.getColor 。我为快速迁移做了一些扩展功能:

@ColorInt
fun Context.getColorCompat(@ColorRes colorRes: Int) = ContextCompat.getColor(this, colorRes)

@ColorInt
fun Fragment.getColorCompat(@ColorRes colorRes: Int) = activity!!.getColorCompat(colorRes)

@ColorInt
fun Resources.getColorCompat(@ColorRes colorRes: Int) = ResourcesCompat.getColor(this, colorRes, null)

【讨论】:

以上是关于在 Android 6.0 Marshmallow (API 23) 上不推荐使用 getColor(int id)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 6.0 Marshmallow 中访问相机?

何时在运行时请求 Android Marshmallow 6.0 的权限?

Android 6.0 Marshmallow BLE 连接问题

Android 6.0 (MarshMallow) 上的 HttpURLConnnection 请求失败

在 Android 6.0 Marshmallow (API 23) 上不推荐使用 getColor(int id)

AndroidHttpClient 和 HttpGet API 在 Android 6.0 Marshmallow (API 23) 中已弃用