- Using vector assets in Android apps
- Understanding Android’s vector image format: VectorDrawable
- Android devices come in all sizes, shapes and screen densities. That’s why I’m a huge fan of using resolution…
- Draw a Path: Rendering Android VectorDrawables
- In the previous article, we looked at Android’s VectorDrawable format, going into its benefits and capabilities.
- AndroidX First
- 1. Enable Support
- 2. Load with AndroidX
- In Practice
- Views without compat attributes
- Nested d rawable s
- Out of process loading
- X Marks the Spot
- Векторная иконка приложения для Андроид — полное руководство.
- Прежде чем мы начн ём
- Подготовка файлов
- Настройка файлов конфигурации
Using vector assets in Android apps
In previous posts we’ve looked at Android’s VectorDrawable image format and what it can do:
Understanding Android’s vector image format: VectorDrawable
Android devices come in all sizes, shapes and screen densities. That’s why I’m a huge fan of using resolution…
Draw a Path: Rendering Android VectorDrawables
In the previous article, we looked at Android’s VectorDrawable format, going into its benefits and capabilities.
In this post we’ll dive into how to use them in your apps. VectorDrawable was introduced in Lollipop (API 21) and is also available in AndroidX (as VectorDrawableCompat ) bringing support all the way back to API 14 (over 99% of devices). This post will outline advice for actually using VectorDrawable s in your apps.
AndroidX First
From Lollipop onward, you can use VectorDrawable s anywhere you would use other drawable types (referring to them using the standard @drawable/foo syntax) but I would instead recommend to always use the AndroidX implementation. This obviously increases the range of platforms you can use them on but more than this, it enables backporting of features and bug fixes to older platforms too. For example, using VectorDrawableCompat from AndroidX enables:
- Both nonZero and evenOdd path fillTypes —the two common ways of defining the inside of a shape, often used in SVGs ( evenOdd added to platform impl in API 24)
- Gradient & ColorStateList fills/strokes (added to platform impl in API 24)
- Bug fixes
In fact, AndroidX will use the compat implementation even on some platforms where a native implementation exists (currently APIs 21–23) to deliver the above benefits. Otherwise it delegates to the platform implementation, so still receives any improvements on newer releases (for example VectorDrawable was re-implemented in C in API 24 for increased performance).
For these reasons you should always use AndroidX, even if you’re fortunate enough to have a minSdkVersion of 24. There’s little downside and if/when VectorDrawable is extended with new capabilities in the future and they’re also added to AndroidX, then they’ll be available straight away without having to revisit your code.
To use the AndroidX vector support, there are 2 things that you need to do:
1. Enable Support
You need to opt in to AndroidX vector support in your app’s build.gradle :
This flag prevents the Android Gradle Plugin from generating PNG versions of your vector assets if your minSdkVersion is versions resources. That means if you declare a VectorDrawable in res/drawable/ it will move it to res/drawable-v21/ for you as it knows this is when the VectorDrawable class was introduced.
This prevents attribute ID clashes — the attributes you use in VectorDrawable s ( android:pathData , android:fillColor etc) each have an integer ID associated with them, which were added in API 21. On older versions of Android, there was nothing preventing OEMs from using any ‘unclaimed’ IDs, making it unsafe to use a newer attribute on an older platform.
This versioning would prevent the asset from being accessed on older platforms, making a backport impossible—the gradle flag disables this versioning for vector drawables. This is why you use android:pathData etc within your vectors rather than having to switch to app:pathData etc like other backported functionality.
2. Load with AndroidX
When loading drawables you need to use methods from AndroidX which provide the backported vector support. The entry point for this is to always load drawables with AppCompatResources.getDrawable . While there are a number of ways to load drawables (because reasons), you must use AppCompatResources if you want to use compat vectors. If you fail to do this, then you won’t hook into the AndroidX code path and your app might crash when trying to use any features not supported by the platform you’re running on.
VectorDrawableCompat also offers a create method. I’d recommend always using AppCompatResources instead as this adds a layer of caching.
If you want to set drawables declaratively (i.e. in your layouts) then appcompat offers a number of *Compat attributes that you should use instead of the standard platform ones:
- Don’t: android:button
- Do: app:buttonCompat
- Don’t: android:drawableStart android:drawableTop etc.
- Do: app:drawableStartCompat app:drawableTopCompat etc.
As these attributes are part of the appcompat library, be sure to use the app: namespace. Internally these AppCompat* views use AppCompatResources themselves to enable loading vectors.
If you want to understand how appcompat swaps out the TextView etc you declare for an AppCompatTextView which enables this functionality then check out this article: https://helw.net/2018/08/06/appcompat-view-inflation/
In Practice
These requirements effect the way you might create a layout or access resources. Here are some practical considerations.
Views without compat attributes
Unfortunately there are a number of places you may want to specify drawables on views that don’t offer compat attributes (e.g. there’s no indeterminateDrawableCompat attribute for ProgressBar s) i.e. anything not listed above. It’s still possible to use AndroidX vectors, but you’ll need to do this from code:
If you are using Data Binding then this can be accomplished using a custom binding adapter:
Note that we don’t want data binding to load the drawable for us (as it doesn’t use AppCompatResources to load drawables currently) so can’t refer to the drawable directly like @ <@drawable/foo>. Instead we want to pass the drawable id to the binding adapter, so need to import the R class to reference it:
Nested d rawable s
Some drawable types are nestable e.g. StateListDrawable s, InsetDrawable s or LayerDrawable s contain other child drawables. The AndroidX support works by explicitly knowing how to inflate elements (also animated-vector s and animated-selector s, but we’ll focus on static vectors today). When you call AppCompatResources.getDrawable , it peeks at the resource with the given id and if it is a vector (i.e. the root element is ), it manually inflates it for you. Otherwise, it hands it off to the platform to inflate — when doing so, there’s no way for AndroidX to re-insert itself back into the process. That means that if you have an InsetDrawable containing a vector and ask AppCompatResources to load it for you, it will see the tag, shrug, and hand it to the platform to load. It therefore will not get a chance to load the nested so this will either fail (on API AppCompatResources to inflate the vector and then create the InsetDrawable drawable manually.
One exception is a recent addition to AndroidX (from appcompat:1.0.0 ) back-ported AnimatedStateListDrawable s. This is a version of StateListDrawable with animated transitions between states (in the form of AnimatedVectorDrawables ). But there is nothing requiring you to declare transitions. So if you just need a StateListDrawable which can inflate child vectors using AndroidX, then you could use this:
There is a way to enable vectors in nested drawables using AppCompatDelegate#setCompatVectorFromResourcesEnabled but it has a number of drawbacks. Be sure to read the javadoc carefully.
Out of process loading
Sometime you need to provide drawables in places where you don’t control when or how they are loaded. For example: notifications, homescreen widgets or some assets specified in your theme (e.g. setting android:windowBackground which is loaded by the platform when creating a preview window). In these cases you aren’t responsible for loading the drawable so there’s no opportunity to integrate AndroidX support and you cannot use vectors pre-API 21 😞.
You can of course use vectors on API 21+ but be aware that you might not enjoy the features/bugfixes provided by AndroidX. For example while it’s great that AndroidX backports fillType=»evenOdd» , a vector which uses this outside of AndroidX support on an API 21–23 device won’t understand this attribute. For this specific example, I’ll cover how to convert fillType at design time in the next article. Otherwise, you may need to provide alternate resources for different API levels:
Note that we need to include the anydpi resource qualifier here in addition to the api level qualifier. This is due to the way that resource qualifier precedence works; any asset in drawable- dpi would be considered a better match then one in just drawable-v21 .
X Marks the Spot
Hopefully this article has highlighted the benefits of using the AndroidX vector support and some limitations that you need to be aware of. Using the AndroidX support both enables vectors on more platform versions and backports functionality but also sets you up to receive any future updates.
Now that we understand both why and how you should use vectors, the next article dives into how to create them.
Coming soon: Creating vector assets for Android
Coming soon: Profiling Android VectorDrawable s
Источник
Векторная иконка приложения для Андроид — полное руководство.
Aug 15 · 4 min read
Однажды копаясь в Андроид документации я с большим удивлением заметил, что в SDK к версии 26 были до б авлены не только адаптивные иконки, но и возможность совсем отказаться от растровых иконок лаунчера на новейших версиях Андроид. Это значит, что вам вовсе не нужно создавать по растровому ассету к каждому разрешению экрана воспользоваться одним/двумя векторными файлами для всех возможных разрешений! Так как растровые иконки достаточно увесистые вы можете таким образом сэкономить много килобайтов в размере приложения. Тут как и везде есть свои моменты и к сожалению я не нашел в интернете полного описания всего процесса. Ну что же, значит пришла моя пора заполнить этот пробел! Ниже вы найдёте видео процесса изготовления единой векторной иконки для приложения, а руководство также доступно на английском и чешском языках.
Прежде чем мы начн ём
Избавится от растровых изображений в целой аппликации — мечта многих оптимизаторов. Особенно если приложения не большое а растровые иконки, при неправильном изготовлении весят почти четверть общего размера приложения. Но тут как и везде есть свои недостатки, давайте поговорим о них, возможно в вашем случае векторная икона — не вариант. Итак:
- Векторный формат в ОС Андроид был введен в версии 21, в качестве иконки приложения в лаунчере векторные изображения можно использовать только в версиях 26 и выше. Это значит, что если Ваше приложение должно поддерживать и более старые версии — Вам все равно придется иметь в наличии растровые иконки. Так что бонус тут не большой.
- Векторный формат который используется в ОС Андроид это не привычные нам SVG/EPS/AI и так далее, это формат XML, а это значит очень ограниченное использование. Этот формат не поддерживает атрибуты стилей, т.е. какие либо эффекты, блендинг, даже простейшие тени, блюр. Вы можете видеть начале видео, что происходит с тенями — они просто пропадают. Если у вас достаточно умелый график в команде, то в принципе это ограничение можно обойти переведя например тени в простые градиенты от полного цвета в абсолютно прозрачный итд. Если же у вас вовсе нет векторного оригинала или там слишком много эффектов — возможно игра не стоит свеч.
На этом минусы заканчиваются. Если ваше приложение должно запускаться лишь на устройствах которые ещё получают закладки безопасности (т.е. в момент написания статьи SDK версии 27+) или же использует какие то новшества современных Андроид систем/датчиков/устройств — векторная иконка отличный выбор. Вы можете сэкономить в несколько раз как на размере так и на файлах для иконки, имея лишь 1-2 файла изображения и пару файлов с их описанием! Звучит круто? Тогда ниже вы найдете рецепт того как это все приготовить.
Подготовка файлов
Я не буду вдаваться в подробности создания файлов иконки, так как они абсолютно идентичны остальным адаптивным иконкам. В интернете буквально тонны всевозможных шаблонов для адаптивных иконок и руководств для них. Можно использовать их все, с той лишь разницей, что в результате мы будем использовать файлы SVG а не PNG. Т.е. это будет один или два файла: первый с задним фоном, который должен иметь область для параллакс эффекта и файл переднего плана. В моем примере я использую вариант где задним фоном служит просто цвет, так что у меня будет один файл с описанием цвета и один файл с векторной графикой.
Итак если вы имеете файл(ы) SVG, то в следующем шаге нам понадобится Android Studio, впрочем если вы занимаетесь разработкой для ОС Андроид, вы и так знаете этот софт. Это бесплатное ПО можно скачать по адресу:
Важно! Векторные ассеты можно создавать лишь в версии 4.2.2 и выше.
Запустите студию, откройте свой проект, после загрузки выберете вкладку Project (первая вкладка слева сверху). В папке с ресурсами с помощью правого клика мыши выведите контекстное меню. В нем выберете первый элемент — New, затем Vector Asset. Откроется Asset Studio, в нем выберете тип: Локальный файл и путь через кнопку с папкой. Проверьте как иконка выглядит и нажмите кнопку Next. Тут вы увидите путь и название к вашему XML файлу с векторной иконкой. Повторите для второго файла если вы используете вектор как в переднем так и на заднем плане. Готово.
Настройка файлов конфигурации
И так изображения готовы, но ваш проект пока не знает пути к ним и как их отобразить. Вам нужно будет добавить/изменить несколько файлов:
- build.gradle — здесь необходимо включить поддержку векторных файлов, просто добавьте эти две строки в конфигурацию и зависимости:
- в папку с ресурсами добавьте папку “ mipmap-anydpi-v26”, т.е. как видно из названия это ассеты для любого DPI в версиях ОС выше 26. В нем будут два файла: ic_launcher_round.xml и ic_launcher.xml в которых необходимо описать что использовать как фон а что как передний план. В моем случае это цвет для фона и векторная графика для переднего плана.
- Ну и на конец то что мы описали в предыдущем пункте нужно добавить в папку drawable а также если вы использовали цвет в качестве фона — описать этот цвет в colors.xml.
Теперь система знает как, где и что, использовать в качестве иконки приложения в лаунчере. Запустите чистую инсталляцию и проверьте результаты своей работы. Как видите, техническая часть достаточно простая (если сравниватъ с PNG иконками).
В результате VCS должна показать вот такие изменения:
Как минимум две новые строки в файле:
./app/build.gradle
Новая папка “ mipmap-anydpi-v26” с двумя файлами:
./app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
./app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Один XML файл с изображением переднего плана:
./app/src/main/res/drawable/ic_launcher_foreground.xml
И либо описание цвета в качестве фона:
./app/src/main/res/values/colors.xml
либо изображение:
./app/src/main/res/drawable/ic_launcher_background.xml (в данной конфигурации отсутствует).
В ссылке ниже вы найдете все необходимые файлы из примера показанного в видео. Можете использовать их как пример для своего приложения. Спасибо за внимание!
Источник