Content Based Theme в Android приложении
Предисловие
Классическая ситуация: допустим у нас есть какой-то RecyclerView, элементы которого - карточки с картинками.
В этой статье мы будем раскрашивать MaterialCardView и её дочерние элементы в цвета, сочетающиеся с цветами изображения. Для этого воспользуемся DynamicColors API.
Мы не будем использовать Compose, на эту тему уже есть несколько статей с его использованием.
Заготовка
Для наших экспериментов создадим какой-то абстрактный data-класс, который будет нашим элементом списка в RecyclerView:
У него есть image для хранения картинки, title для хранения заголовка, а также tag для хранения каких-нибудь тегов.
В реальном проекте, наверное, image будет не Drawable, а ссылкой на картинку. Всё-таки изображения обычно подгружаются из сети. Но мы сделаем так для упрощения примера: все наши картинки будут лежать в ресурсах приложения.
Ну и давайте сразу создадим какой-то простенький адаптер для RecyclerView:
Ну и в классе Activity в onCreate создадим простой список из элементов и подключим адаптер к RecyclerView:
Теперь у нас есть простенькое приложение со списком карточек.
Теперь наша задача - заставить карточки раскрашиваться в зависимости от изображения на них.
В целом можно придумать много способов это реализовать. В этом примере мы воспользуемся DynamicColors API.
К сожалению, Dynamic Colors API не будет работать на версиях Android ниже 12ой. Однако если у вас есть желание реализовать подобное на ранних версиях Android - можно воспользоваться Palette API.
Красим карточки
Раскрашиванием карточек будет заниматься адаптер для RecyclerView. В документации, написанной Google, есть прекрасный пример того, как это можно реализовать.
В нашем ViewHolder модифицируем метод bind. Для начала возьмём bitmap из imageView и сожмём его. Так мы ускорим процесс определения цветовой схемы карточки:
Теперь можно воспользоваться прекрасным функционалом wrapContextIfAvailable из Dynamic Colors API. Создадим контекст, используя compressedBitmap в качестве сontentBasedSource:
Дело остаётся за малым: перекрасить элементы ViewHolder цветами темы нового контекста:
Стоит учесть, что wrapContextIfAvailable - достаточно трудоёмкая функция. Чтобы избежать лагов - можно воспользоваться корутинами.
Таким образом метод bind нашего ViewHolder выглядит следующим образом:
Теперь карточки в нашем RecyclerView будут раскрашиваться в зависимости от цвета изображения. Цвет карточки мы выбрали ColorSecondaryContainer, а цвет заголовка: ColorPrimary. Вы можете выбрать какие-то другие цвета на свой вкус.
Результат
Заключение
Надеюсь, статься была полезной для вас. Вы можете ознакомиться с исходным кодом на GitHub. Всем удачи!