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

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

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

abb8fc3f00674918939354faeece7655.png


Исходник:


    
    Created with Sketch.
    
        
            
            
        
    
    

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

In smile.svg:
ERROR@ line 5  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:

396124a7b0e84d1ca3295acf35f40730.png


    

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

3ee823cef3e3469c9bc283e2cdc6516a.png


    

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



    
        
            
            
            
        
    
    

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

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

2aebc0e923bb48e7835974ced1d96137.png

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

Комментарии (10)

  • 2 апреля 2017 в 23:03

    0

    И отправила мне эти иконки в svg формате, с чувством выполненного долга.

    Я правильно понял, что можно было и не в svg? Ну т.е. вместо всего этого достаточно было их конвертировать в растровый формат?
    • 2 апреля 2017 в 23:05

      0

      Разумеется. Раньше так и делали, в нескольких разрешениях в png, но на дворе ведь 21-й век
      • 2 апреля 2017 в 23:12 (комментарий был изменён)

        0

        А вам не кажется, что сохранить картинку растром в трех разрешениях — это наоборот, чуть более прогрессивный способ решения задачи, чем «в лоб» заставить тужиться несколько миллионов устройств (или какая там у вас будет аудитория :-), просчитывая несколько слоёв векторной картинки? Тем более что ваш эксперимент наверняка компании обошелся в несколько раз дороже, чем полчаса времени дизайнера на пересохранение всех пиктограмм в приложении.
        • 3 апреля 2017 в 00:54

          0

          Я вам скажу по секрету, что начал программировать с языка ассемблера и не признавал лет 10 ничего иного, как раз из соображений недопущения перегрева Вселенной :) Но правда оказалась в том, что всем пофиг. Никому не нужны оптимально работающие программы длиной 500 байт.
          В данной же ситуации наличие векторных изображений сильно сокращает время разработки, поскольку программисту можно отмасштабировать картинки согласно спецификациям, а кроме того, они используются на разных View в разных размерах
          • 3 апреля 2017 в 01:16

            0

            В данной же ситуации наличие векторных изображений сильно сокращает время разработки,

            Я по поводу «сильно сокращает» возражаю. Экономия времени там близка к нулю на самом деле (Android с версии, если память не изменяет, 2.1 умеет автоматически подбирать изображение по разрешению экрана и делать ресемплинг), а если посчитать ещё и время на предложенную вами доводку svg до ума, то вместо экономии будет жуткий оверхед. Android 6+, если не ошибаюсь, сейчас это примерно треть действующих устройств, да? А у вас даже для пятой нужно руками допиливать каждый ресурс. Да ну к лешему такое «сильно сокращает».
        • 3 апреля 2017 в 01:19

          0

          У вас, видимо, никогда не было телефона с 1.5 гигабайтами доступной для приложений памяти.
          • 3 апреля 2017 в 01:48

            0

            Чудес же не бывает. Оно только в ресурсах векторное и маленькое. А при отображении оно все равно будет растеризоваться, да ещё и с просчетами «на лету» всех тех эффектов, и памяти на все свои слои будет кушать. Наоборот, если весь этот процесс заранее сделают на компьютере дизайнера, ваш телефон только спасибо скажет.
            • 3 апреля 2017 в 01:49

              0

              Не оперативной памяти, флэша.
              • 3 апреля 2017 в 02:49

                0

                Оперативки в таком случае, значит, еще меньше?
                • 3 апреля 2017 в 02:57

                  0

                  Гигабайт. Полистайте маркет с сортировкой по цене.

© Habrahabr.ru