getColor (int id) устарел в Android 6.0 Marshmallow (API 23)

719

Resources.getColor(int id)Метод является устаревшим.

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

Что мне делать?

Аракс
источник
26
Используйте ContextCompat.getColor (context, R.color.color_name)
Ашокчакраварти Нагараджан,
С помощью этого метода, упомянутого выше: getColor (context, R.color.your_color); Не понятно, как получить «контекст». Это не сработает, просто поместив контекст в моем случае, Android Studio 3.2. Я считаю, что это работает для меня. .setTextColor (Color.RED).
Гарри

Ответы:

1348

Начиная с библиотеки поддержки Android 23,
добавлен новый метод getColor ()ContextCompat .

Его описание с официального JavaDoc:

Возвращает цвет, связанный с конкретным идентификатором ресурса.

Начиная с M, возвращаемый цвет будет стилизован для указанной темы контекста.


Итак, просто позвоните :

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


Вы можете проверить ContextCompat.getColor() исходный код на GitHub .

Аракс
источник
1
Это похоже на решение, но что мы должны делать, когда получим ошибку «Должен ли здесь передавать разрешенный цвет вместо идентификатора ресурса»? Насколько я могу судить, это, вероятно, потому, что Lint не распознает новый API библиотеки поддержки, поэтому, возможно, стоит добавить аннотацию @SuppressWarnings ("ResourceAsColor")? Мне это не очень нравится.
Стан
1
Привет @Stan, не могли бы вы предоставить фрагмент кода с вызовом метода, который запускает Lint "ResourceAsColor"?
Аракс
"int color = ContextCompat.getColor (this, R.color.orange);" а затем "span = new ForegroundColorSpan (color);". Слово, которое подчеркнуто красным, это «цвет», где я передаю его «new ForegroundColorSpan ()».
Стэн
1
@MonicaLabbao о ... извините, я неправильно понял ваш комментарий! :)
Аракс
3
ContextCompatApi23 эта отметка об ошибке означает, что вы ссылаетесь на ContextCompat
Webserveis
499

ТЛ; др:

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

Объяснение:

Вам нужно будет использовать ContextCompat.getColor () , который является частью библиотеки Support V4 (она будет работать для всех предыдущих API).

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

Если вы еще не используете библиотеку поддержки, вам нужно добавить следующую строку в dependencies массив внутри вашего приложения build.gradle(примечание: это необязательно, если вы уже используете библиотеку appcompat (V7) ):

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

Если вам небезразличны темы, в документации указано, что:

Начиная с M, возвращаемый цвет будет стилизован для указанной темы контекста.

Melvin
источник
4
Это должен быть выбран как правильный ответ. Потому что в данном звене Android Docs, это сказать : « Начиная с M, возвращаемый цвет будет стиль для темы указанного контекста в. »
Ошибки случаются
1
скомпилируйте 'com.android.support:appcompat-v7:23.0.1'
G O'Rilla
@G O'Rilla Как вы можете видеть из документации, ContextCompatкласс поставляется из SupportV4. AppcompatV7 тоже работает, так как полагается на SupportV4. Как говорится в документации библиотеки поддержки , 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в ответ.
Мелвин
1
Спасибо @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);
Лара Раффл Коулз
1
@Melvin. Что именно это означает, что «цвет будет стилизован под заданную тему контекста». Похоже, можно определить разные цвета для одного и того же цвета в зависимости от темы. Как это сделать точно?
RobertoCuba
47

Я не хочу включать библиотеку поддержки только для 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 <23.

И вот что я использую в 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);
Алекс Ванг
источник
4
Глядя на исходный код, это именно то, как библиотека поддержки делает это. Я нацеливаю API> = 21, поэтому я не хочу включать полный jar для этих нескольких строк. Обратите внимание, что вы можете отключить предупреждение в Android Studio, добавив "// noinspection deprecation" над устаревшим вызовом. И используйте контекст действия, а не контекст приложения, иначе вы можете потерять информацию о теме.
personne3000
2
Это должен быть правильный ответ, хотя библиотека поддержки может быть более подходящей для будущего, и я согласен с тем, что, если это единственная причина, по которой вы включаете библиотеку поддержки, вам лучше включить эти несколько строк.
Антонимори
30

В Android Marshmallow многие методы устарели.

Например, чтобы получить цвет использовать

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

Также, чтобы получить возможность рисования

ContextCompat.getDrawable(context, R.drawable.drawble_name);
Ашокчакраварти Нагараджан
источник
3
откуда берется переменная context? я должен инициализировать это? Я не могу заставить его работать. Мне кажется, что Андроинду предстоит долгий путь; это ошеломляет меня, насколько я изо всех сил пытаюсь получить цвет из ресурса XML! Ух ты
ColdTuna
29

Для всех пользователей Kotlin:

context?.let {
    val color = ContextCompat.getColor(it, R.color.colorPrimary)
    // ...
}
Пол Спизбергер
источник
На самом деле должно быть val color = ContextCompat.getColor(context, R.color.colorPrimary). Переменная «это» может быть чем угодно, но это должен быть контекст .
Скотт Биггс
itв этом случае context, так как я использую, context?.let {чтобы проверить context, не является ли NULL. Функция getColor()принимает только ненулевой контекст. Подробнее о letтом, как его использовать, читайте здесь : kotlinlang.org/docs/reference/scope-functions.html#let
Пол Спизбергер,
4

В вашем 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
    }
}
Ирвин Жуан
источник
1

Используйте getColor(Resources, int, Theme)метод из ResourcesCompatбиблиотеки поддержки Android.

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

Я думаю , что лучше отражать ваш вопрос , чем getColor(Context, int)из ContextCompatтак вы спрашиваете Resources. До уровня API 23 тема не будет применена, и метод вызывается, getColor(int)но у вас не будет устаревшего предупреждения. Тема тоже может быть null.

Pedro
источник
1
Если вы передадите null в качестве аргумента Theme, возвращенный цвет НЕ будет стилизован для текущей темы. Так что это может быть неправильно.
Аракс
1

Если ваш текущий мин. Уровень API равен 23, вы можете просто использовать его,getColor() как мы используем, чтобы получить строковые ресурсы getString():

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

Вы можете ограничить уровень API ниже 23:

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

Из ресурсов .

Из ContextCompat AndroidX .

Из поддержки ContextCompat

Blasanka
источник
0

Я тоже расстроился. Моя потребность была очень простой. Все, что я хотел, это цвет 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;
}
Стивен Смит
источник