Так вышло, что в моем текущем проекте мне пришлось столкнуться с проблемой. Дизайнер согласовала с заказчиком набор иконок, раскрашенных простым линейным градиентом. И отправила мне эти иконки в svg формате, с чувством выполненного долга. Гугление выявило, что поддержка градиентов в vector drawable начинается только с SDK 24+.
Тем не менее, используя небольшую хитрость, оказалось возможным обойти ограничение, что я и продемонстрирую на примере.
В качестве рабочей картинки возьмем следующую:
Исходник:
<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:
<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 на белый:
<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, а переделывать уже не хочется):
Приятного кодинга!
Автор: br0x