Android: оттенок с помощью DrawableCompat
Я пытаюсь подкрасить изображение до уровня API Android 21. Я успешно тонировал элементы, используя:
<android:tint="@color/red"/>
однако я не могу понять, как это сделать через код на ImageView:
Drawable iconDrawable = this.mContext.getResources().getDrawable(R.drawable.somedrawable);
DrawableCompat.setTint(iconDrawable, this.mContext.getResources().getColor(R.color.red));
imageView.setImageDrawable(iconDrawable);
Я попытался установить TintMode, но это, кажется, не делает ничего другого. Я неправильно использую класс совместимости V4 DrawableCompat?
7 ответов
самый простой способ оттенить кросс-платформенный (если вам не нужен ColorStateList):
drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
Не забудьте мутировать Drawable перед применением фильтра.
в случае, если кто-то должен использовать DrawableCompat
тонировка без влияния на другие чертежи, вот как вы это делаете с mutate()
:
Drawable drawable = getResources().getDrawable(R.drawable.some_drawable);
Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
wrappedDrawable = wrappedDrawable.mutate();
DrawableCompat.setTint(wrappedDrawable, getResources().getColor(R.color.white));
который можно упростить до:
Drawable drawable = getResources().getDrawable(R.drawable.some_drawable);
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable.mutate(), getResources().getColor(R.color.white));
ранее тонировка не поддерживалась DrawableCompat
.
Начиная с библиотеки поддержки 22.1 вы можете сделать это, но вам нужно сделать это следующим образом:
Drawable normalDrawable = getResources().getDrawable(R.drawable.drawable_to_tint);
Drawable wrapDrawable = DrawableCompat.wrap(normalDrawable);
DrawableCompat.setTint(wrapDrawable, getResources().getColor(R.color.colorPrimaryLight));
ответы здесь не работают для pre-lollipop-устройств (SupportLib 23.4.0), но я опубликовал обходной путь, который работает для API 17 и выше:https://stackoverflow.com/a/37434219/2170109
следующий код был протестирован и работает на API 17, 19, 21, 22, 23 и N Preview 3:
// https://stackoverflow.com/a/30928051/2170109
Drawable drawable = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.vector));
image.setImageDrawable(drawable);
/*
* need to use the filter | https://stackoverflow.com/a/30880522/2170109
* (even if compat should use it for pre-API21-devices | https://stackoverflow.com/a/27812472/2170109)
*/
int color = ContextCompat.getColor(context, R.color.yourcolor);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
DrawableCompat.setTint(drawable, color);
} else {
drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
Если вы посмотрите на исходный код DrawableCompat вы увидите, что для любой версии метод ничего не делает.
идея DrawableCompat, кажется, просто не сбой в старых версиях, а не фактически предоставление этой функциональности.
с библиотекой поддержки 22.1 вы можете использовать DrawableCompat для подкраски drawables.
DrawableCompat.wrap (Drawable) и setTint (), setTintList () и setTintMode () будут просто работать: нет необходимости создавать и поддерживать отдельные чертежи только для поддержки нескольких цветов!
я поделюсь своим решением здесь, потому что это может сэкономить кому-то время.
Я ImageView
с вектором drawable используется в качестве источника drawable (на самом деле, это был вектор поддержки Drawable С Библиотека Поддержки Android 23.3). Итак, сначала я завернул его так:
mImageView.setImageDrawable(DrawableCompat.wrap(mImageView.getDrawable()));
и после этого я попытался применить к нему оттенок так:
DrawableCompat.setTint(
mImageView.getDrawable(),
getResources().getColor(R.color.main_color)
);
не повезло.
Я пытался позвонить mutate()
на обернутом drawable, как и на оригинальном drawable-все равно не повезло. invalidate()
призвал mImageView
сделал свое дело.