Векторные картинки с градиентом в Андроид 5.0

в 19:55, , рубрики: android, vector drawable, Разработка под android

Так вышло, что в моем текущем проекте мне пришлось столкнуться с проблемой. Дизайнер согласовала с заказчиком набор иконок, раскрашенных простым линейным градиентом. И отправила мне эти иконки в svg формате, с чувством выполненного долга. Гугление выявило, что поддержка градиентов в vector drawable начинается только с SDK 24+.
Тем не менее, используя небольшую хитрость, оказалось возможным обойти ограничение, что я и продемонстрирую на примере.

В качестве рабочей картинки возьмем следующую:

Векторные картинки с градиентом в Андроид 5.0 - 1


Исходник:

<svg width="980px" height="980px" viewBox="10 10 980 980" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
    <desc>Created with Sketch.</desc>
    <defs>
        <linearGradient x1="0%" y1="0%" x2="101.999998%" y2="100.999999%" id="linearGradient-1">
            <stop stop-color="#2CF607" offset="0%"></stop>
            <stop stop-color="#038BF3" offset="100%"></stop>
        </linearGradient>
    </defs>
    <path d="M328.5,353 C369.1,353 402,320.1 402,279.5 C402,238.9 369.1,206 328.5,206 C287.9,206 255,238.9 255,279.5 C255,320.1 287.9,353 328.5,353 Z M500,10 C229.4,10 10,229.4 10,500 C10,770.6 229.4,990 500,990 C770.6,990 990,770.6 990,500 C990,229.4 770.6,10 500,10 Z M500,941 C256.5,941 59,743.6 59,500 C59,256.4 256.5,59 500,59 C743.5,59 941,256.4 941,500 C941,743.6 743.5,941 500,941 Z M671.5,353 C712.1,353 745,320.1 745,279.5 C745,238.9 712.1,206 671.5,206 C630.9,206 598,238.9 598,279.5 C598,320.1 630.9,353 671.5,353 Z M720.5,598 C720.5,598 637.8,745 500,745 C362.2,745 279.5,598 279.5,598 C233.4,572.2 189.2,624.9 230.5,671.5 C230.5,671.5 325.4,818.5 500,818.5 C674.6,818.5 769.5,671.5 769.5,671.5 C808.3,616.3 762.5,570.4 720.5,598 Z" id="Shape" stroke="none" fill="url(#linearGradient-1)" fill-rule="nonzero"></path>
</svg>

Пытаемся импортировать оригинальную картинку в Android Studio.

In smile.svg:
ERROR@ line 5 <defs> is not supported
ERROR@ line 11 Unsupported URL value: url(#linearGradient-1)
ERROR@ line 11 Unsupported URL value: url(#linearGradient-1)

Что и следовало ожидать.

Удаляем секцию defs и заменяем атрибут fill каким-нибудь цветом. Параметры градиент-стопов запоминаем, они нам позднее понадобятся. Теперь студия не возражает.
Наш полученный vector drawable:

Векторные картинки с градиентом в Андроид 5.0 - 2

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="980dp"
        android:height="980dp"
        android:viewportWidth="980.0"
        android:viewportHeight="980.0">
    <path
        android:pathData="M318.5,343C359.1,343 392,310.1 392,269.5C392,228.9 359.1,196 318.5,196C277.9,196 245,228.9 245,269.5C245,310.1 277.9,343 318.5,343ZM490,0C219.4,0 0,219.4 0,490C0,760.6 219.4,980 490,980C760.6,980 980,760.6 980,490C980,219.4 760.6,0 490,0ZM490,931C246.5,931 49,733.6 49,490C49,246.4 246.5,49 490,49C733.5,49 931,246.4 931,490C931,733.6 733.5,931 490,931ZM661.5,343C702.1,343 735,310.1 735,269.5C735,228.9 702.1,196 661.5,196C620.9,196 588,228.9 588,269.5C588,310.1 620.9,343 661.5,343ZM710.5,588C710.5,588 627.8,735 490,735C352.2,735 269.5,588 269.5,588C223.4,562.2 179.2,614.9 220.5,661.5C220.5,661.5 315.4,808.5 490,808.5C664.6,808.5 759.5,661.5 759.5,661.5C798.3,606.3 752.5,560.4 710.5,588Z"
        android:strokeColor="#00000000"
        android:fillColor="#00ff00"/>
</vector>

Следующий шаг состоит в том, чтобы сделать картинку «негативной», т.е. цветные участки преобразовать в прозрачные, а все остальное сделать цвета фона, в нашем простейшем примере белым. Для этого достаточно добавить к пути всего один обрамляющий контур (теоретически, может понадобиться изменить направление обхода на противоположное). Заодно, я полностью убрал android:strokeColor и заменил fillColor на белый:

Векторные картинки с градиентом в Андроид 5.0 - 3

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="980dp"
        android:height="980dp"
        android:viewportWidth="980.0"
        android:viewportHeight="980.0">
    <path
        android:pathData="M0,0L980,0L980,980L0,980
        M318.5,343C359.1,343 392,310.1 392,269.5C392,228.9 359.1,196 318.5,196C277.9,196 245,228.9 245,269.5C245,310.1 277.9,343 318.5,343ZM490,0C219.4,0 0,219.4 0,490C0,760.6 219.4,980 490,980C760.6,980 980,760.6 980,490C980,219.4 760.6,0 490,0ZM490,931C246.5,931 49,733.6 49,490C49,246.4 246.5,49 490,49C733.5,49 931,246.4 931,490C931,733.6 733.5,931 490,931ZM661.5,343C702.1,343 735,310.1 735,269.5C735,228.9 702.1,196 661.5,196C620.9,196 588,228.9 588,269.5C588,310.1 620.9,343 661.5,343ZM710.5,588C710.5,588 627.8,735 490,735C352.2,735 269.5,588 269.5,588C223.4,562.2 179.2,614.9 220.5,661.5C220.5,661.5 315.4,808.5 490,808.5C664.6,808.5 759.5,661.5 759.5,661.5C798.3,606.3 752.5,560.4 710.5,588Z"
        android:fillColor="#ffffff"/>
</vector>

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

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:top="0.5dp"
        android:right="0.5dp"
        android:left="0.5dp"
        android:bottom="0.5dp">
        <shape android:shape="rectangle">
            <gradient
                android:startColor="#2CF607"
                android:endColor="#038BF3"
                android:angle="135"
                android:type="linear" />
            <size
                android:width="64dp"
                android:height="64dp">
            </size>
        </shape>
    </item>
    <item android:drawable="@drawable/ic_smile" />
</layer-list>

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

Результат вполне достойный (только я случайно поменял местами startColor и endColor, а переделывать уже не хочется):

Векторные картинки с градиентом в Андроид 5.0 - 4

Приятного кодинга!

Автор: br0x

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js