- Android Vector Drawables
- Why Vector Drawables?
- The VectorDrawable Class
- The AnimatedVectorDrawable Class
- Performance tradeoff for Vector Drawables
- Легко переходим на векторный формат картинок вместо нарезки под разные плотности экранов в Android 4.0+. Часть 1 из 2
- Библиотека BetterVectorDrawable
- Подключаем библиотеку
- Включаем перехват ресурсов
- Удобный способ
- Быстрый способ
- Ручной способ
- Используем vector drawable
- VectorDrawable — часть первая
Android Vector Drawables
There are two basic ways an image can be represented in: Bitmaps and Vector Drawables. Normal Bitmaps are represented in the form of pixels in a grid. A Vector Drawable defines the image in the form of geometry, i.e as a set of points in the cartesian plane, connected through lines and curves, with their associated color information.
In this post we’ll be focuss
Android Vector Drawables
There are two basic ways an image can be represented in: Bitmaps and Vector Drawables. Normal Bitmaps are represented in the form of pixels…
Note: Changes here will affect how your story appears in public places like Medium’s homepage — not the story itself.
Add or change tags (up to 5) so readers know what your story is about
Android×
Add a tag…
Allow curators to recommend my story to interested readers.ing on static Vector Drawables and some of their advanced features. Animated Vector Drawables will be covered very briefly.
Why Vector Drawables?
Vector Drawables are,
All Bitmaps have a specific resolution, which when displayed on a different density display may pixelate or might introduce unwanted artifacts. Vector Drawables look sharp on each display independent of display density, i.e. the same file is resized for different screen densities.
A Bitmap of higher resolution means more pixels. More pixels means larger file size. Vector Drawables do not store pixels therefore they are of the same size independent of display density. This results in smaller APK files and less developer maintenance.
Vector Drawables are highly flexible. One can also animate them using multiple XML files.
The support for Vector Drawables was added in API Level 21(Lollipop). Prior to this release if anyone wanted to represent images through Vector Graphics they had to do it manually though Java Code. If Bitmaps were used, developers had to use different images, one for each display resolution. Imagine using animated Bitmaps in such a situation!
There are two classes that help you use Vector Drawables: VectorDrawable and AnimatedVectorDrawable.
The VectorDrawable Class
This class defines a static drawable object. It is defined in a manner similar to the SVG format.
It follows a tree hierarchy consisting of groups and paths. The path contains the actual geometric data to draw the object. The group contains data for transformation of the shape. The path is always a leaf of the tree. The path will be joined in same order in which it appears in the file.
The group text is an internal node of the tree. A path object inherits all the transformation of it’s ancestor groups.
Let’s take a look at a sample Vector Graphic as an SVG file and its corresponding XML Vector Drawable.
android:fillColor=”#000000″
android:fillAlpha=”.3″
android:pathData=”M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h5.47L13 7v1h4V5.33C17 4.6 16.4 4 15.67 4z”/>
android:fillColor=”#000000″
android:pathData=”M13 12.5h2L11 20v-5.5H9L12.47 8H7v12.67C7 21.4 7.6 22 8.33 22h7.33c0.74 0 1.34–0.6 1.34–1.33V8h-4v4.5z”/>
This Vector Drawable renders an image of a battery in charging mode.
There’s a lot more you can do with Vector Drawables. For example you can specify the tint for the image. You needn’t worry if the SVG the designer gave has the right shade of grey you need. The same Vector Drawable renders with different colors according to the set theme.
All you need to do to set the tint is add this attribute to the vector:
You can also use theme colors for specific parts of your image. For example in order to use colorPrimary in you image add this attribute to your path:
Many a times we need to change the color of icons depending on the state of the button. These changes might be as minor as a different colored stroke. You can accomplish this using different colored images, but when the rendering is the same for most of the part, using ColorStateList inside the Vector Drawable is a much better way. You can avoid a lot of duplication in this manner.
The way to accomplish this is the same as that of a regular ColorStateList. Create a ColorStateList in the color resource directory, and use a reference to it in the fillColor attribute in the path.
If your ColorStateList is csl_image.xml, the add this line:
Vectors also support gradients. You can have three types of gradients:
We can also define individual color stops using tag to get more fine grained gradients as show below:
This sets the color at 72% of the gradient direction parameter.
Just as we define ColorStateLists in the color resource directory, we can define gradients and then add their reference in our Vector Drawable in the fillColor attribute.
An alternative to this is to define the gradient using inline resource syntax to embed it inside the vector definition itself as shown below.
Here the AAPT(Android Asset Packaging Tool) will extract this to a color resource at build time and insert a reference for it.Gradients are very useful in situations where you need shadows in Vector Drawables. Vector don’t support shadows, but it can be faked using gradients. You can also use it to create customized spinners using a radial gradient.
If the gradient doesn’t fill the entire image, you may choose to so any of the following:
This is the default mode. It just continues the color outwards from the last offset point
You may accomplish this by adding the following line in the gradient:
This repeats the gradient until the whole image is filled.
You may accomplish this by adding the following line in the gradient:
This goes back and forth through the gradient.
You may accomplish this by adding the following line in the gradient:
We can also make gradients that do not go from color to color but have regions of solid color.
This can be accomplished by using the same color between two color stops, as shown below:
The AnimatedVectorDrawable Class
This class adds animation to the properties of a VectorDrawable. We can define animated vector drawables in two ways:
A VectorDrawable file, an AnimatedVectorDrawable file and an animator XML file.
- Using a single XML file
- You can also merge related XML files using XML Bundle Format.
To support vector drawable and animated vector drawable on devices running platform versions lower than Android 5.0 (API level 21), VectorDrawableCompat and AnimatedVectorDrawableCompat are available through two support libraries: support-vector-drawable and animated-vector-drawable, respectively.
Support Library 25.4.0 and higher supports the following features:
- Path Morphing (PathType evaluator) Used to morph one path into another path.
- Path Interpolation Used to define a flexible interpolator (represented as a path) instead of the system-defined interpolators like LinearInterpolator.
Support Library 26.0.0-beta1 and higher supports the following features:
- Move along path The geometry object can move around, along an arbitrary path, as part of an animation.
For more information about Animated Vector Drawables you can refer to the links posted at the end of the post.
Performance tradeoff for Vector Drawables
Although the XML file used for Vector Drawables is usually smaller than conventional PNG images, it has significant computational overhead at runtime in case the drawn object is complex. When the image is rendered for the first time, a Bitmap cache is created to optimize redrawing performance. Whenever the image needs to be redrawn, the same Bitmap cache is used unless the image size is changed. So, for example you rotate your device, if the size of the rendered image remains the same, it will be rendered using the same cach otherwise the cache will be rebuilt. Therefore in comparison to raster images they take longer to render for the first time.
As the time taken to draw them is longer, Google recommends a maximum size of 200 x 200 dp.
Источник
Легко переходим на векторный формат картинок вместо нарезки под разные плотности экранов в Android 4.0+. Часть 1 из 2
Обычно дизайн приложения рисуется в векторном редакторе (например, Sketch), но типичным форматом картинок в приложении под Android является растровый (как правило, PNG). При разработке приложения необходимо для каждого векторного изображения заниматься утомительной работой по изготовлению набора растровых картинок для разных плотностей экранов. Количество таких комплектов может доходить до шести по числу возможных плотностей: ldpi, mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi (плотность xxxhdpi необходима только для иконки приложения). При верстке иногда приходится задать в разметке явные размеры для изображения, что может потребовать перемасштабирования растровой картинки, а это, в свою очередь, наверняка приведет к появлению артефактов. К тому же наличие нескольких комплектов картинок отрицательно сказывается на размере выходного apk.
Все решают эти проблемы по-разному: кто-то пытается подключить SVG-библиотеку к проекту, кто-то генерирует нарезку с помощью утилиты.
Как мне кажется, наиболее правильным решением является отказ от использования растровой графики в приложении в пользу векторной. При этом хотелось бы по максимуму задействовать системные возможности. В Android 5.0 появился VectorDrawable – поддержка векторного формата для картинок, которые размещаются в виде ресурсов с расширением xml в папке drawable. На такие картинки можно ссылаться обычным образом из XML-разметки.
Использование VectorDrawable было бы отличным решением, если бы не необходимость поддержки устройств с Android 4.0+, коих большинство. VectorDrawable нет в support library и неизвестно, когда он там появится (хотя начало положено). Но не стоит печалиться: есть замечательная библиотека BetterVectorDrawable с открытым исходным кодом и лицензией Apache 2.0, которая фактически переносит VectorDrawable на Android 4.0+, предоставляя тот же интерфейс, и позволяет при необходимости использовать системный VectorDrawable на Android 5.0+. Нужно отметить, что есть еще пара аналогичных библиотек, но они не стоят Вашего внимания, поскольку не дают полноценно ссылаться на vector drawable ресурсы из разметки.
К сожалению, разработчики Android не предусмотрели поддержку в VectorDrawable градиентов, текстур, масок. Это небольшая проблема, но об этом следует помнить при составлении дизайна приложения. Если от этих элементов невозможно отказаться, то можно как прежде использовать в отдельных местах растровую графику / shape drawable, преимущественно перейдя на вектор.
Итак, чтобы перейти на векторный формат картинок в приложении надо:
- Подключить к приложению библиотеку BetterVectorDrawable
- Выгрузить из векторного редактора изображения в SVG-формате
- С помощью конвертера сконвертировать их все сразу в XML-формат vector drawable
- Положить полученные файлы в директорию приложения res/drawable
- Использовать векторные изображения в разметке и в коде как обычные ресурсы
- Profit
Библиотека BetterVectorDrawable
Подключаем библиотеку
Чтобы подключить библиотеку к приложению достаточно добавить одну строчку в секции dependencies файла build.gradle, расположенном в директории модуля приложения:
Библиотека распространяется через репозиторий JCenter, который используется по умолчанию в новых проектах Android Studio.
Если Вы создавали проект давно, то, возможно, у Вас используется репозиторий Maven Central. Чтобы это проверить, надо в файлах build.gradle поискать вхождения строки
и добавь рядом с ней
Включаем перехват ресурсов
Библиотеке необходимо передать список идентификаторов векторных ресурсов, чтобы она понимала, какие из них являются vector drawable. BetterVectorDrawable будет перехватывать обращения к ним и создавать экземпляры VectorDrawable .
Поскольку передать список нужно один раз, лучше всего это сделать в методе onCreate() класса Application , для чего придется создать его наследника:
И указать этого наследника в манифесте приложения:
Существует три способа передать список: удобный, быстрый и ручной.
Удобный способ
Метод findAllVectorResourceIdsSlow сканирует все drawable XML-ресурсы и убеждается, что каждый возвращаемый ресурс является vector drawable. Разработчики советуют использовать этот метод по умолчанию, тем не менее, это наименее производительный способ, т.е. на старых устройствах время запуска приложения может существенно возрасти.
На Google Nexus 5 в приложении с 400 векторными ресурсами findAllVectorResourceIdsSlow отрабатывает менее чем за 150 мс.
Быстрый способ
Метод findVectorResourceIdsByConvention подразумевает, что названия всех векторных ресурсов начинаются на vector_ или заканчиваются на _vector. Соглашение по именованию нужно указать с помощью параметра resourceNamingConvention .
На Google Nexus 5 в приложении с 400 векторными ресурсами findVectorResourceIdsByConvention отрабатывает менее чем за 20 мс.
Ручной способ
Просто передается список всех идентификаторов векторных картинок. 0 мс.
Используем vector drawable
Или из разметки:
Как видите, все просто.
Если у Вас возникли вопросы, то можно задать их мне либо посмотреть демо-приложение. О проблемах с библиотекой лучше сообщать разработчикам в GitHub.
В следующей части мы обсудим конвертацию изображений из SVG в vector drawable XML.
Источник
VectorDrawable — часть первая
Предлагаю вашему вниманию перевод статьи «VectorDrawables – Part 1» с сайта blog.stylingandroid.com.
По долгу службы потребовалось мне как-то разобраться с векторной графикой. Во время поиска наткнулся я на серию статей под названием “VectorDrawable” в блоге https://blog.stylingandroid.com/. Ответов на все интересующие меня вопросы я, конечно, не нашел, но статьи очень понравились своей последовательностью и четко выверенным объемом необходимого материала. Решил поделиться переводом этих статей с обитателями хабра.
Я не переводил названия, activity, bitmap и тому подобное, потому что считаю, что так легче воспринимать информацию, ведь разработчики, в силу профессии, эти слова в русском варианте практически никогда не у потребляют. Далее следует перевод:
Одна из действительно интересных новых фишек в Lollipop – это включение VectorDrawable и связанных с ним классов, которые обеспечивают чрезвычайно мощные новые возможности для добавления сложной векторной графики (позволяет гораздо удобнее масштабировать изображения не зависимо от размеров экрана и плотности, чем растровые изображения), а также предоставляет несколько мощных инструментов для анимации оных. В этой серии статей мы рассмотрим некоторые из преимуществ, которые они нам дают. Так же рассмотрим, как можно получить действительно впечатляющие результаты из относительно небольшого количества кода.
Векторная графика – способ описания графических элементов используя геометрические фигуры. Они особенно хорошо подходят для графических элементов, созданных в приложениях, таких как Adobe Illustrator или Inkscape, где простые геометрические формы могут быть объединены в гораздо более сложные элементы. Работа с растровой графикой, с другой стороны, определяет значение цвета для каждого пикселя и особенно хорошо подходит для фото. Большим преимуществом использования векторной графики (в соответствующих случаях) является то, что изображения рендерятся в рантайме и размеры автоматически высчитываются в зависимости от плотности пикселей. Таким образом получается четкая картинка с плавными линиями, независимо от возможностей устройства. Векторные картинки, как правило, занимают значительно меньший объем памяти, чем их растровый аналог. Однако, векторные изображения требуют больше вычислительных мощностей для отрисовки, что может быть проблемой при большом количестве сложных графических элементах.
Векторная графика в андроиде была реализована с использованием нового класса – VectorDrawable, который был введен в Lollipop. Это означает, что для графических элементов, которые хорошо подходят для векторного представления мы можем заменить растровые изображения в папках mdpi, hdpi, xhdpi, xxhdpi, и xxxhdpi на один VectorDrawable в папке Drawable, который, с большой вероятностью, займет даже меньше пространства на диске, чем растровое изображение для mdpi.
Чтобы продемонстрировать это, давайте рассмотрим следующий файл svg (найти его можно по ссылке https://code.google.com/archive/p/svg-android/downloads):
Этот svg-файл занимает 2265 байт, если мы отрисуем его в bitmap с размерами 500 х 500 пикселей, и сохраним как png, тогда он займет уже 13272 байта, плюс к этому, мы должны будем использовать несколько таких картинок для разный плотностей экрана. Но SVG – это не то же самое, что VectorDrawable, поэтому мы не можем использовать его непосредственно. Тем не менее, VectorDrawable поддерживает некоторые элементы SVG. Основные компоненты, которые мы будем использовать из нашего SVG – это path. Давайте посмотрим на исходный код SVG:
Немного разберемся. Есть некоторые атрибуты родительского элемента , которые определяют размер 500х500, Есть элемент (group), который определяет границы – его мы будем игнорировать. Есть еще один элемент с Это и есть изображение логотипа, которое нам нужно. Он состоит из шести элементов , которые определяют голову, правый глаз, левый глаз, левая рука, тело и ноги, правая рука. Атрибут “fill” определяет цвет заливки (и мы можем видеть, что все они зеленые, за исключением глаз, которые залиты белым цветом), а атрибут “d” содержит маршрут линий, из которых состоит элемент. Для тех, кто хочет разобраться более детально в элементе , следует изучить SVG Path Specification, но для данной статьи это не важно, потому что мы можем просто взять их, как они есть, и использовать в наших VectorDrawables.
Итак, давайте создадим наш VectorDrawable:
Мы создали родительский элемент , который содержит информацию о размерах изображения, внутрь которого поместили элемент с шестью элементами , которые были немного модифицированы, по сравнению с svg – файлом. В данной статье поле “name” служит только для облегчения понимая того, где какой элемент. В следующих статьях они буду использоваться. Получившийся файл по-прежнему может похвастаться скромным размером в 2412 байт.
Теперь мы можем использовать этот файл как любой другой drawable:
… и если мы запустим это, то увидим красивую отрисовку:
Так что теперь мы можем существенно уменьшить размер APK, если мы используем VectorDrawable, где это уместно. Так же это позволяет упростить разработку приложения, особенно, если нужно добавлять поддержку новых плотностей экрана. Тем не менее, это не все, на что способен VectorDrawable. В следующей части статьи мы рассмотрим, как его анимировать.
Исходники к этой части статьи можно найти здесь.
Источник