[Разработка мобильных приложений, Разработка под Android] Как исправить баг с Drawable.setTint в API 21 Android SDK
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет, в этой заметке наш android-разработчик Влад Титов расскажет о том, как решить проблему с использованием инструмента изменения цвета для Drawable. Поехали.В 21 версии API Android SDK появился универсальный инструмент изменения цвета для всех Drawable - Drawable.setTint(int color). Но как раз-таки в этой самой версии он не работает у некоторых наследников Drawable, а именно GradientDrawable, InsetDrawable, RippleDrawable и всех наследников DrawableContainer. Если посмотреть в исходники API 21, скажем, GradientDrawable (прямого наследника Drawable), мы не найдем переопределенного метода setTint и его вариаций. А это значит, что в данной реализации разработчики попросту не поддержали эту функцию.Проблему условно решили в библиотеке обратной совместимости. Сейчас ее можно найти по артефакту androidx.core:core. Чтобы поддержать tinting на версиях 14-22, были созданы обертки WrappedDrawableApi14 и WrappedDrawableApi21. Последняя является наследницей первой и, по сути, не несет логики по поддержке окрашивания. Чтобы обернуть оригинальный Drawable, нужно всего лишь подать его в метод DrawableCompat.wrap(Drawable). Основная идея состоит в том, что сам ColorStateList тинта хранится в обертках, а у оригинального Drawable изменяется цветовой фильтр при изменении состояния Drawable.
final ColorStateList tintList = mState.mTint;
final PorterDuff.Mode tintMode = mState.mTintMode;
if (tintList != null && tintMode != null) {
final int color = tintList.getColorForState(state, tintList.getDefaultColor());
if (!mColorFilterSet || color != mCurrentColor || tintMode != mCurrentMode) {
setColorFilter(color, tintMode);
mCurrentColor = color;
mCurrentMode = tintMode;
mColorFilterSet = true;
return true;
}
} else {
mColorFilterSet = false;
clearColorFilter();
}
Данный кусок кода будет вызываться каждый раз при вызове Drawable.setState(int[] stateSet).При использовании этих оберток вы теряете возможность вызывать специфические методы для конкретных Drawable. Так, например, при оборачивании GradientDrawable вы не сможете управлять градиентом, так как обертка в своем интерфейсе не имеет методов таких, как setShape, setGradientType и.т.п. Чтобы получить доступ к данным методам, обернутый Drawable придется развернуть (DrawableCompat.unwrap(Drawable)). Но в таком случае вы теряете тинт. Если он у вас состоял только из одного цвета, ничего страшного, ведь этот цвет сохранится как цветовой фильтр в оригинальном Drawable. Но если тинт был stateful, цвета для стейтов, отличных от текущего, будут потеряны.Выходом из сложившейся ситуации может быть пример, приведенный далее. Если ваш тинт состоит лишь из одного цвета, вы можете в любой момент выполнить следующие действия:
val wrapped = DrawableCompat.wrap(drawable)
wrapped.setTint(...)
drawable = DrawableCompat.unwrap(wrapped)
После чего смело делать дальше свои дела.В ином случае есть смысл воспользоваться следующим решением:
class GradientDrawableWrapper(
val original: GradientDrawable,
var ColorStateList tint
) {
fun get(): Drawable {
return wrap()
}
fun setShape(@Shape shape: Int) {
original.setShape(shape)
}
// other specific method proxies...
private fun wrap(): Drawable {
val wrapped = DrawableCompat.wrap(original)
wrapped.setTint(tint)
return wrapped
}
}
Такое решение выглядит немного объемным, но полностью решает указанную проблему.
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка под Android, Kotlin] MVVM и выбор элементов в адаптере — Базовый адаптер
- [Разработка мобильных приложений, Интерфейсы, Геоинформационные сервисы, Развитие стартапа] Разработка интерфейса Драйва: от запуска стартапа до глубокого анализа UI. Доклад Яндекса
- Сертификаты Let's Encrypt перестанут восприниматься на 33% Android-устройств
- [Разработка мобильных приложений, Разработка под Android, Тестирование мобильных приложений, Облачные сервисы] Отладка приложений в экосистеме Huawei: облачная платформа для дебаггинга, сервисы A/B- и открытого тестирования
- [Разработка веб-сайтов, Разработка под iOS, Разработка мобильных приложений, Разработка под Android] Хабр ПРО. Mobile-разработка: своя команда vs аутсорс
- [Разработка под Android, Профессиональная литература] Книга «Android. Программирование для профессионалов. 4-е издание»
- [Разработка мобильных приложений] Как Kotlin Multiplatform экономит время на разработку. Личный опыт создания игрового приложения для KotlinConf 2019
- [Разработка под Android, Kotlin] Solving coding problems with Kotlin: Collection functions
- [Разработка мобильных приложений, Разработка игр, Игры и игровые приставки] Как я создал мобильную игру для своего ребёнка
- [Информационная безопасность, IT-инфраструктура] Зачем нужны сертифицированные средства защиты информации?
Теги для поиска: #_razrabotka_mobilnyh_prilozhenij (Разработка мобильных приложений), #_razrabotka_pod_android (Разработка под Android), #_bagi (баги), #_android, #_sdk, #_mobilnaja_razrabotka (мобильная разработка), #_mobilnoe_prilozhenie (мобильное приложение), #_razrabotka_mobilnyh_prilozhenij (
Разработка мобильных приложений
), #_razrabotka_pod_android (
Разработка под Android
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:30
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет, в этой заметке наш android-разработчик Влад Титов расскажет о том, как решить проблему с использованием инструмента изменения цвета для Drawable. Поехали.В 21 версии API Android SDK появился универсальный инструмент изменения цвета для всех Drawable - Drawable.setTint(int color). Но как раз-таки в этой самой версии он не работает у некоторых наследников Drawable, а именно GradientDrawable, InsetDrawable, RippleDrawable и всех наследников DrawableContainer. Если посмотреть в исходники API 21, скажем, GradientDrawable (прямого наследника Drawable), мы не найдем переопределенного метода setTint и его вариаций. А это значит, что в данной реализации разработчики попросту не поддержали эту функцию.Проблему условно решили в библиотеке обратной совместимости. Сейчас ее можно найти по артефакту androidx.core:core. Чтобы поддержать tinting на версиях 14-22, были созданы обертки WrappedDrawableApi14 и WrappedDrawableApi21. Последняя является наследницей первой и, по сути, не несет логики по поддержке окрашивания. Чтобы обернуть оригинальный Drawable, нужно всего лишь подать его в метод DrawableCompat.wrap(Drawable). Основная идея состоит в том, что сам ColorStateList тинта хранится в обертках, а у оригинального Drawable изменяется цветовой фильтр при изменении состояния Drawable. final ColorStateList tintList = mState.mTint;
final PorterDuff.Mode tintMode = mState.mTintMode; if (tintList != null && tintMode != null) { final int color = tintList.getColorForState(state, tintList.getDefaultColor()); if (!mColorFilterSet || color != mCurrentColor || tintMode != mCurrentMode) { setColorFilter(color, tintMode); mCurrentColor = color; mCurrentMode = tintMode; mColorFilterSet = true; return true; } } else { mColorFilterSet = false; clearColorFilter(); } val wrapped = DrawableCompat.wrap(drawable)
wrapped.setTint(...) drawable = DrawableCompat.unwrap(wrapped) class GradientDrawableWrapper(
val original: GradientDrawable, var ColorStateList tint ) { fun get(): Drawable { return wrap() } fun setShape(@Shape shape: Int) { original.setShape(shape) } // other specific method proxies... private fun wrap(): Drawable { val wrapped = DrawableCompat.wrap(original) wrapped.setTint(tint) return wrapped } } =========== Источник: habr.com =========== Похожие новости:
Разработка мобильных приложений ), #_razrabotka_pod_android ( Разработка под Android ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:30
Часовой пояс: UTC + 5