ChatGPT解决这个技术问题 Extra ChatGPT

getColor(int id) deprecated on Android 6.0 Marshmallow (API 23)

The Resources.getColor(int id) method has been deprecated.

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

What should I do?

Use ContextCompat.getColor(context, R.color.color_name)
With this method mentioned above: getColor(context, R.color.your_color); It is not clear how to get the "context". It won't work by just putting context there in my case, android studio 3.2. I find this works for me. .setTextColor(Color.RED).

C
Community

Starting from Android Support Library 23,
a new getColor() method has been added to ContextCompat.

Its description from the official JavaDoc:

Returns a color associated with a particular resource ID Starting in M, the returned color will be styled for the specified Context's theme.

So, just call:

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

You can check the ContextCompat.getColor() source code on GitHub.


This looks like the solution, but what are we supposed to do when we get an error "Should pass resolved color instead of resource id here"? As far as I can tell it's probably because Lint does not recognise the new API of the Support Library, so maybe just adding an annotation @SuppressWarnings("ResourceAsColor") is the way to go? I don't like it much though.
Hi @Stan, can you please provide the code snippet with the method call that triggers the "ResourceAsColor" Lint?
@MonicaLabbao oh... sorry, I misunderstood your comment! :)
ContextCompatApi23 this mark error supossed you reference ContextCompat
I don't get what's the use of the "theme". Are there any examples?
R
Rafael Tavares

tl;dr:

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

Explanation:

You will need to use ContextCompat.getColor(), which is part of the Support V4 Library (it will work for all the previous APIs).

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

If you don't already use the Support Library, you will need to add the following line to the dependencies array inside your app build.gradle (note: it's optional if you already use the appcompat (V7) library):

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

If you care about themes, the documentation specifies that:

Starting in M, the returned color will be styled for the specified Context's theme


This should be the selected as correct answer. Because in the given link of Android Docs, it say "Starting in M, the returned color will be styled for the specified Context's theme."
compile 'com.android.support:appcompat-v7:23.0.1'
@G O'Rilla As you can see in the documentation, the ContextCompat class comes from SupportV4. AppcompatV7 works too as it relies on SupportV4. As they say on the 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.. So it makes sense not to put AppcompatV7 in the answer.
Thanks @Melvin, here is my example if of use: 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. What exactly does it mean the the 'color will be styled to the specified Context's theme'. Sounds like one can define different colors for the same color id depending on the theme. How is this done exactly?
A
Alex Vang

I don't want to include the Support library just for getColor, so I'm using something like

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

I guess the code should work just fine, and the deprecated getColor cannot disappear from API < 23.

And this is what I'm using in 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);

Looking at the source code, this is exactly how the support library does it. I target API >= 21 so I don't want to include a full jar for these few lines. Note that you can suppress the warning in Android Studio by adding "//noinspection deprecation" above the deprecated call. And use an Activity context, not an Application context, or you might lose theme information.
This should be the correct answer, although support library can be more future proof choice, I do agree that if this is the only reason you include the support library for, you better off including these couple of lines.
M
Marko

In Android Marshmallow many methods are deprecated.

For example, to get color use

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

Also to get drawable use

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

where does the variable context come from? do i have to initialize it? I can't get it to work. To me it seem like Androind has a long way to go; it blows my f mind how much I am struggling to get a f color from a xml resource!! Wow
h
halfer

For all the Kotlin users out there:

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

Actually should be val color = ContextCompat.getColor(context, R.color.colorPrimary). The variable "it" could be anything, but it needs to be a Context.
it is in this case the context, since I use context?.let { to check if the context is not null. The function getColor() only accepts a non-null context. Read more here about let and how to use it: kotlinlang.org/docs/reference/scope-functions.html#let
J
Jamie

In Kotlin, you can do:

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

if requireContext() is accessible from where you are calling the function. I was getting an error when trying

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

y
younes

in activity used ContextCompat

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

in Adaper

private Context context;


context.getResources().getColor()

I
Irvin Joao

In Your RecyclerView in Kotlin

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
    }
}

B
Blasanka

If your current min. API level is 23, you can simply use getColor() like we are using to get string resources by getString():

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

You can constraint for API Levels below 23:

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

but to keep it simple, you can do like below as accepted answer:

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

From Resources.

From ContextCompat AndroidX.

From ContextCompat Support


N
N. Osil

If you don't necessarily need the resources, use parseColor(String):
Color.parseColor("#cc0066")


a
android developer

Use the getColor(Resources, int, Theme) method of the ResourcesCompat from the Android Support Library.

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

I think it reflect better your question than the getColor(Context, int) of the ContextCompat since you ask about Resources. Prior to API level 23, the theme will not be applied and the method calls through to getColor(int) but you'll not have the deprecated warning. The theme also may be null.


If you pass null as Theme argument, the returned color will NOT be styled for the current theme. So it might be incorrect.
@araks Isn't it the same as the deprecated call though? After all, you get the Resources instance in both cases, and not the Context.
@androiddeveloper they've deprecated the call exactly for that reason: to avoid loading non themed resources. If you pass null you invalidate all the code migration effort to fix this deprecation and expose yourself to the risk of loading non themed resources (mainly drawables) without any clear indication on why they're not working as intended. So you should alway provide a Theme instance from your current Activity/Fragment or use the ContextCompat.get* methods.
@araks You mean the cases that drawables have "?attr/" ?
a
android developer

The best equivalent is using ContextCompat.getColor and ResourcesCompat.getColor . I made some extension functions for quick migration:

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

P
Peter Mortensen

I got frustrated too. My need was very straightforward. All I wanted was the ARGB color from the resources, so I wrote a simple static method.

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