Android color from float

Добавляем Floating Action Button в свое Android приложение

В этом году на презентации Google I/O был представлен новая версия Android — L. Вместе с этим было представлено много новых плюшек для пользователей и разработчиков. Но одним из главных новшеств, несомненно, было новое решение Google для унификации дизайна — Material Design.

Одним из паттернов Material Design является Floating Action Button.

Что такое Floating Action Button ?

Google говорит, что это «специальный метод для способствования действию». Сама же кнопка имеет форму круга, плавающего над интерфейсом.

Стоит отметить, что Floating Action Button должна отражать только главное действие в приложении.

Быстрая и грязная реализация

Я хотел создать быстрый способ добавления простейшей FAB для своих Android приложений с minSdkVersion = 14 (Ice Cream Sandwich). Я также реализовал анимацию появления/исчезновения и небольшие возможности для кастомизации кнопки.

Весь код доступен в Github Gist (добавьте этот класс в свой проект).

При создании кнопки в XML, я обнаружил некоторые трудности позиционирования View у нашей кнопки над остальными View (в частности, над Navigation Drawer). Я решил реализовать кнопку программно и работать посредством Builder-паттерна, что позволит размещать FAB выше других View в Activity при вызове .create().

Отлично! Но как мне добавить это в свое приложение ?

Добавить Floating Action Button очень даже просто:

Размер кнопки легко изменить посредством вызова .withButtonSize(int size). По умолчанию стоит 72dp.

Заключение

Похоже, что Google будет использовать этот паттерн во многих своих приложениях. И еще до сих пор нет никаких новостей о том, будет ли Google добавлять floating action button в support library, поэтому пока что не стесняйтесь использовать это решение.

Источник

Manipulating images and Drawables with Android’s ColorFilter

Tinting, custom effects and reusability for visual Android app resources

Image and Drawable resources are an integral part of any Android app. Since day (i.e. API level) 1, the Android framework has provided a means of manipulating the colors of these assets on a per-pixel level, as they are drawn to screen, with the ColorFilter class.

The documentation for the base abstract class stipulates that “a color filter can be used with a Paint to modify the color of each pixel drawn with that paint”. This is a powerful tool that can be used for:

  • Applying effects and adjustments to images
  • Tinting of icons and logos

Ultimately this encourages the good practice of reusing resources for scenarios that require different color variations, resulting in reduced app size.

Note: ColorFilter is an abstract class that should never be used directly, and the constructor was deprecated in API level 26. Only the subclasses should be used, which we will discuss further down.

Where can this be used? 🤔

Before we explore the existing subclasses and their capabilities, we need to discuss where we can actually use ColorFilter .

Canvas

As hinted at in the documentation description, we can use ColorFilter when drawing to Canvas in a custom View . Specifically, a ColorFilter is set on a Paint which then affects everything that is drawn with it:

Drawable

A ColorFilter can be applied to a Drawable , which will affect how it is rendered in View s and layouts:

In addition to this, there exists a Drawable convenience function to apply a PorterDuffColorFilter (more on that later):

Lastly, it is important to note that a tint can be applied to a Drawable . This is separate and will be overridden if a ColorFilter is set via either one of the above functions.

ImageView

A ColorFilter can be applied to an ImageView , which will affect how its current image will be rendered:

As with Drawable , convenience functions exist for applying a PorterDuffColorFilter :

Introducing our sample image 🖼️

We are now going to dive into the three subclasses of ColorFilter ( PorterDuffColorFilter , LightingColorFilter and ColorMatrixColorFilter ). In order to demonstrate this, we will make use of a visual aid in the form of a sample image:

Читайте также:  Загрузка андроида с флешки

It has photographic detail while also having “shape” as a result of the transparent areas. This will allow all of the subclasses to be demonstrated.

PorterDuffColorFilter 1️⃣

We have already touched on this briefly. This is a color filter that accepts a single color that is applied to all source pixels along with a Porter-Duff composite mode. There are many modes that are suitable to different scenarios. Typically, this is used to apply a “blanket” color (eg. To tint an icon).

LightingColorFilter 2️⃣

This color filter can be used to simulate lighting effects on an image. The constructor accepts two parameters, the first to multiply the source color ( colorMultiply ) and the second to add to the source color ( colorAdd ).

While the source color alpha channel is not affected, the R, G and B channels are computed like so:

Note: The above is using Android KTX Color extension functions for accessing the red, blue and green channels (alpha is also available).

ColorMatrixColorFilter 3️⃣

This is arguably the most flexible (but also the most complex) color filter.

It is quite similar to LightingColorFilter , in that we can tweak each pixel’s color channels using values that are multiplicative and additive. However, a ColorMatrixColorFilter is constructed with a ColorMatrix , which is essentially a wrapper class for a 4×5 matrix. This gives us 20 values, used in a certain way, that allow us to transform colors using all of the existing channels, including alpha.

Before we dive into using matrices, let’s first take a look at some of the convenience functions offered by ColorMatrix :

Fear not if some of these color concepts do not make sense! The point here is that ColorMatrix offers a lot of flexibility, and these convenience functions are simply matrix operations under the hood.

We know that ColorMatrix wraps a 4×5 matrix. Given this matrix, how do we arrive at our resultant color channels? They are computed like so:

The 4 rows in fact represent the resultant R, G, B and A channels. For each channel, the 5 columns allow you to combine the existing R, G, B, and A channels and a wildcard value in a plethora of ways.

This provides us with a lot of possibilities. We can adjust the brightness/contrast of images, ignore some channels, invert an image or even create basic filters and effects.

Limitations and other options 🛠️

While ColorFilter is powerful and flexible, image manipulation is a vast field and it simply cannot cover everything.

For example, the current pixel value that is being passed through the filter would be handy to know, but is not available. Additionally, you are limited to the three subclasses that ColorFilter currently provides. It appears as if you cannot create a custom subclass, due to native code restrictions.

In instances like this, what other options do we have?

The graphics framework has other useful classes such as Shader and MaskFilter . We could turn to RenderScript , which offers Bitmap utilities that still keep us mostly within traditional Android graphics territory. There is also OpenGL, which is perhaps the most extreme power vs. complexity tradeoff, but opens up all of the possibilities of custom GLSL shaders.

Overall, ColorFilter is still a fantastic tool for working with app resources.

I hope this post has provided some insight into ColorFilter and the flexibility it provides when working with images and Drawable s. If you have any questions, thoughts or suggestions then I’d love to hear from you!

Источник

Полный список

— меняем цвет кисти с помощью ColorFilter

Сначала немного разъяснений по поводу цвета. Думаю, все уже в курсе, что в Android цвет мы обычно получаем путем сочетания трех цветов – красного (Red), зеленого (Green) и синего (Blue). Зовется это RGB. К этому набору можно еще добавить уровень прозрачности (Alpha). Получится ARGB.

Значения этих компонентов мы указываем от 0 до 255. Например, фон экрана, который я использую во всех уроках образуется так (80, 102, 204, 255). Соответственно значения: прозрачность – 80, красный – 102, зеленый – 204, синий – 255.

Если мы все RGB компоненты установим равными 0, то получим черный цвет. Если же все будут 255, то получим белый цвет.

Частенько значения указываются не в десятичной форме, а в шестнадцатеричной. Т.е. от 00 до FF, вместо 0 и 255. В этом случае обычно пишут не ARGB, а AARRGGBB. Например, красный цвет: FFFF0000. Если разбивать на AARRGGBB компоненты, получим AA = FF, RR = FF, GG = 00, BB = 00.

Читайте также:  Bluetooth клавиатура для iphone android

Существуют int-константы для указания цвета. Например Color.RED. Как получить такую int-константу из ARGB компонентов? Есть методы Color.rgb и Color.argb, куда вы передаете RGB или ARGB компоненты, а метод вернет вам int-значение цвета.

А метод Color.parseColor позволит получить вам int-значение из шестнадцатеричной формы: #RRGGBB или #AARRGGBB.

Наследники ColorFilter позволяют нам оказывать влияние на цвет, используемый при рисовании объектов.

ColorMatrixColorFilter

Начнем с ColorMatrixColorFilter. Этот вид фильтра влияет на цвет, используя значения 4х5 матрицы, которую мы ему выдадим.

Алгоритм немного нетривиальный, если вы незнакомы с матрицами из алгебры.

Мы задаем матрицу такого вида

rR, rG, rB, rA, rT
gR, gG, gB, gA, gT
bR, bG, bB, bA, bT
aR, aG, aB, aA, aT

4 строки, в каждой по 5 значений.

И пусть у нас есть некий цвет ARGB, к которому будем фильтр применять. Фильтр возьмет текущие значение цвета и из них, используя матрицу, вычислит новые. Например, новое значение красного (Rn) он посчитает так:

Rn = R * rR + G * rG + B * rB + A * rA + rT

Т.е. значения исходного цвета (R,G,B,A) перемножаем на первые 4 значения (rR, rG, rB, rA) из первой строки матрицы и прибавляем пятое значение (rT) из этой же строки.

Разумеется, нам ничего такого кодить не придется, фильтр сам все рассчитает. От нас требуется только матрицу ему предоставить. Здесь я просто показываю, как оно все внутри работает.

Новое значение зеленого (Gn) получается аналогично, используя исходные RGBA и вторую строку матрицы.

Gn = R * gR + G * gG + B * gB + A * gA + gT

Синий (Bn) и прозрачность (An) – третья и четвертая строки

Bn = R * bR + G * bG + B * bB + A * bA + bT

An = R * aR + G * aG + B * aB + A * aA + aT

Давайте рассмотрим это на примерах.

Project name: P1531_ColorFilter
Build Target: Android 2.3.3
Application name: ColorFilter
Package name: ru.startandroid.develop.p1531colorfilter
Create Activity: MainActivity

cmData – массив float, сюда пишем значения для матрицы.

Переменная cm – это и есть матрица – ColorMatrix. Ей мы даем массив cmData.

Эту матрицу мы указываем при создании фильтра filter. Теперь у фильтра есть матрица и он знает какие преобразования цвета ему необходимо будет произвести.

В методе drawObjects рисуем 4 квадрата – красный, зеленый, синий, белый, и выводим андроид-иконку. На этих объектах мы будет тестировать изменения цвета. Используем кисть paint.

В onDraw рисуем объекты метолом drawObjects, затем для кисти paint применяем фильтр методом setColorFilter и снова выводим объекты. Т.к. при рисовании объектов используется кисть paint, то применение фильтра к кисти повлияет на цвета рисуемых фигур.

Сейчас наша матрица выглядит следующим образом

1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0

Если мы возьмем RGBA и применим матрицу, получим

Rn = R * 1 + G * 0 + B * 0 + A * 0 + 0 = R

Gn = R * 0 + G * 1 + B * 0 + A * 0 + 0 = G

Bn = R *0 + G * 0 + B * 1 + A * 0 + 0 = B

An = R * 0 + G * 0 + B * 0 + A * 1 + 0 = A

Новые значения равны исходным. Т.е. матрица настроена так, что RGBA значения любого цвета вообще не изменятся. Убедимся в этом. Запускаем приложение

Сверху (оригинал) и снизу (после применения фильтра) цвета одинаковы. Фильтр хоть и применился, но ничего не изменил в значениях цветов.

Теперь явно что-то поменялось. Давайте смотреть, что именно

Был красный цвет c RGBA = (255,0,0,255). Применим фильтр:

Rn = 255 * 1 + 0 * 0 + 0 * 0 + 255 * 0 + 0 = 255

Gn = 255 * 0 + 0 * 0 + 0 * 0 + 255 * 0 + 0 = 0

Bn = 255 * 0 + 0 * 0 + 0 * 0 + 255 * 0 + 0 = 0

An = 255 * 0 + 0 * 0 + 0 * 0 + 255 * 1 + 0 = 255

Новые RGBA значения получились такими (255,0,0,255). Т.е. для красного цвета ничего не поменялось. Это видно и на скриншоте, красный квадрат на месте.

А вот зеленый стал черным, смотрим почему

RGBA зеленого = (0,255,0,255). Применяем фильтр.

Rn = 0 * 1 + 255 * 0 + 0 * 0 + 255 * 0 + 0 = 0

Gn = 0 * 0 + 255 * 0 + 0 * 0 + 255 * 0 + 0 = 0

Bn = 0 * 0 + 255 * 0 + 0 * 0 + 255 * 0 + 0 = 0

An = 0 * 0 + 255 * 0 + 0 * 0 + 255 * 1 + 0 = 255

Новые RGBA значения зеленого = (0,0,0,255), а это черный. Тем же путем и синий (0,0,255,255) стал черным.

А белый (255,255,255,255) после преобразования

Rn = 255 * 1 + 255 * 0 + 255 * 0 + 255 * 0 + 0 = 255

Gn = 255 * 0 + 255 * 0 + 255 * 0 + 255 * 0 + 0 = 0

Bn = 255 * 0 + 255 * 0 + 255 * 0 + 255 * 0 + 0 = 0

An = 255 * 0 + 255 * 0 + 255 * 0 + 255 * 1 + 0 = 255

стал таким (255,0,0,255) – т.е. красным. Скриншот это подтверждает.

Т.е. применив фильтр, мы для всех цветов «обнулили» значения синего (B) и зеленого (G). Оставили только красную (R) составляющую. Это видно и на андроид-иконке.

Но тут важно понимать одну вещь. Мы не выкрасили все в красный цвет. Мы полностью убрали зеленый и синий, а красный оставили в том значении, в каком он был.

Т.е. в красном квадрате значение красного было 255. Таким и осталось.

В синем и зеленом квадратах значение красного было 0. Таким и осталось.

Читайте также:  Android studio billing in app

В андроид-иконке видно, что красный неоднородный, где-то светлее, где-то темнее. Т.е. изначально иконка была нарисована разными оттенками, в которых были использованы различные RGB комбинации. А мы в этих комбинациях убрали G и B, оставили только R. Т.е. где R был, например 50, остался 50. Где был 150 – остался 150. А G и B теперь везде = 0.

Давайте настроим матрицу так, чтобы красный везде стал максимальным. Независимо от первоначального значения. А синий и зеленый снова будем обнулять.

Мы убрали коэффициент 1 из первого числа первой строки. Т.е. теперь новое значение R уже не будет равно старое значение R умноженное на 1. Теперь оно будет умножаться на 0. Но последнее число первой строки = 255. Оно будет прибавлено к нулю и мы получим полный красный цвет на замену первоначальным оттенкам красного.

Синий и зеленый также станут красными. Т.к. G и B значения мы в них обнулим, а R будет равен 255, т.е. (255,0,0,255).

Теперь изменим матрицу так, чтобы обнулялся только синий. Красный и зеленый компоненты останутся неизменны.

Убрав из синего цвета (0,0,255,255) синюю компоненту мы получили черный (0,0,0,255).

А убрав из белого цвета (255,255,255,255) синюю компоненту мы получили желтый (255,255,0,255).

красный + зеленый + синий = белый

белый – синий = красный + зеленый = желтый.

Мы меняли компоненты цветов (RGB), теперь давайте попробуем поменять прозрачность (A). Напомню, что если A = 255, то цвет абсолютно непрозрачен. Если A = 0, то цвет совсем не виден.

Мы поставили коэффициент 0.3 для вычисления нового значения прозрачности. Т.е. An = A * 0.3. Т.е. все цвета станут прозрачными на 30% от текущего уровня.

Еще пара примеров матриц, которые я нашел в инете:

У матрицы также есть несколько методов, которые позволяют настраивать ее значения.

setScale – позволяет нам указать на какие значения необходимо умножать RGBA значения цвета.

Перепишем конструктор DrawView:

При создании ColorMatrix мы не использовали массив, и матрица создалась такой, какая была у нас в самом первом примере, т.е. ничего не меняющая. Но сейчас мы ее поднастроим.

Используем метод setScale. Его входящие параметры – это коэффициенты соответственно для R, G, B и A компонентов.

Т.е. значения 1, 1, 0, 0.5f настроят матрицу так, что

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

Похоже на то, что было в четвертом примере, только прозрачность другая.

Также есть интересный метод setSaturation. Отвечает за насыщенность цветов. Принимает на вход значения от 0 до 1.

Если задать 0, то получим черно-белую картинку.

Если например 0.5f, то будет половина насыщенности

По умолчанию значение этого метода = 1, все цвета при этом будут такими, какими должны.

Есть еще метод setRotate. Это поворот относительно одного из RGB компонентов на указанное кол-во градусов. Я, честно говоря, его не понимаю и объяснить его смысл не могу. Возможно, он будет понятен тем, кто активно использует графические редакторы и работает с цветом.

LightingColorFilter

LightingColorFilter принимает на вход два цвета

mul – RGB-компоненты этого цвета будут умножены на соответствующие RGB-компоненты исходного цвета. Причем, компоненты mul надо рассматривать, как числа в диапазоне от 0 до 1. Т.е. если в mul компонент, например, R равен 255, то R-компонент исходного цвета останется без изменений (умножение на 1). Если в mul компонент R = 0, то R-компонент обнулится (умножение на 0). Если в mul компонент R = 127, то R-компонент уменьшится в два раза (умножение на 0.5)

add — RGB-компоненты этого цвета будут прибавлены к соответствующим RGB-компонентам исходного цвета, а результат урезан до 255.

В общем, должен сказать, что все эти игры с цветом для меня темный лес. Я не очень понимаю, какую практическую пользу можно вынести их этих механизмов. Но теперь мы имеем понятие как они работают и как ими пользоваться. Возможно, когда-нибудь это пригодится при работе с графикой.

Есть еще третий ColorFilter класс: PorterDuffColorFilter. О нем поговорим в одном из следующих уроков.

На следующем уроке:

— разбираем PorterDuff-режимы используя PorterDuffXfermode

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Оцените статью