Tag Archives: VectorDrawable

Vector Graphics in Android: Converting SVG to VectorDrawable

Vector graphics native support has long been on the wishlist of Android developers who have to export their vector graphics as a rasterized PNG file for each different device resolution.

Introducing VectorDrawable

The good news is that the Android SDK now has native support for basic vector graphic definitions. With the release of API 21 (Android 5.0) came VectorDrawable.

android.graphics.drawable.VectorDrawable

The most important things to understand if you want to implement drawables in your app using VectorDrawable are:

  • VectorDrawable is not implemented in the support library, therefore it will only work in Android 5.0+ (VectorDrawable support for older APIs may be coming soon to the support library)
  • VectorDrawable supports paths using the same definition as the ‘d’ attribute in the SVG format
  • VectorDrawable does not read or support the SVG format
  • VectorDrawable does not support gradients and patterns
  • VectorDrawable does not support numbers using scientific E notation (as commonly used in SVG)

While it is important to understand that the SVG format is not supported, it doesn’t necessarily mean you can’t convert your existing simple SVG files. A VectorDrawable is specified through XML, with the format of the path data in the VectorDrawable using the same format as the specification for SVG paths. This allows us to reformat the XML in some SVG files to convert it into a VectorDrawable XML file.

If you are looking to use SVG files directly in your Android app take a look at this comparison of 3rd party solutions:

https://androidbycode.wordpress.com/2015/02/27/vector-graphics-in-android-part-1-svg/

Case Study: Converting SVG to VectorDrawable

The penguin in the image below (Attribution: Larry Ewing) has been rendered from a SVG image.  SVG images such as this can not be converted into a VectorDrawable as it uses LinearGradient in the original source.NewTux

Below is a rendered image of the flag of Ghana, it is also rendered from an SVG however as this image doesn’t have a gradient and only includes simple shapes, it is most suitable for conversion to a VectorDrawable. We will use this image as to illustrate how to convert an SVG into a VectorDrawable.

Flag of Ghana

SVG Images are described using the XML format. The above image contains 4 elements; three stripes and a star. The SVG XML source may appear as follows:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg"
  width="450"
  height="300"
  id="svg2"
  version="1.1">
<rect
  width="450"
  height="300"
  fill="#006b3f"
  id="rect4" />
<rect
  width="450"
  height="200"
  fill="#fcd116"
  id="rect6" />
<rect
  width="450"
  height="100"
  fill="#ce1126"
  id="rect8" />
<path
  d="M225,100 L257.492,200 172.427,138.197H277.573L192.508,200z"
  fill="#000"
  id="path10" />
</svg>

If we want to create this same image as an Android VectorDrawable the first thing we need to do is ensure all items are described using paths. Remember only paths are supported in VectorDrawable.  To do this we convert each rect definition in the SVG image to use a path definition. The following XML shows the new path objects:


<path
  style="fill:#006b3f"
  d="m 0,0 450,0 0,300 -450,0 z" />
<path
  style="fill:#fcd116"
  d="m 0,0 450,0 0,200 -450,0 z" />
<path
  style="fill:#ce1126"
  d="m 0,0 450,0 0,100 -450,0 z" />

The next step is to convert the XML into Android’s new VectorDrawable format.  To do this we need to keep the path and color definitions but replace the formatting.  The XML should now look like this:


<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="450dp"
android:height="300dp"
android:viewportWidth="450"
android:viewportHeight="300">

<group>
  <path
    android:fillColor="#006b3f"
    android:pathData="M 0,0 l 450,0 0,300 -450,0 z" />
  <path
    android:fillColor="#fcd116"
    android:pathData="M 0,0 l 450,0 0,200 -450,0 z" />
  <path
    android:fillColor="#ce1126"
    android:pathData="M 0,0 l 450,0 0,100 -450,0 z" />
  <path
    android:fillColor="#000"
    android:pathData="M225,100 L257.492,200 172.427,138.197H277.573L192.508,200z" />
</group>
</vector>

This VectorDrawable file should be named with an .xml extension and placed in your drawables folder so it can be accessed in your Java source code or layout definition as you would with any other drawable.

The good news is you don’t need to step through this process by hand each time, there are tools to help you out. I have documented this process as it is important to know what and how to hand code the xml format as the conversion tools will not work all of the time so you may need to tweak the code from time to time.

To convert your SVG file to use only paths you can use Inkscape (The awesome open source SVG tool).  Open the SVG file in Inkscape and select all items you want to convert to a path.  Then from the Path menu select Object to path. If you use Adobe Illustrator then you need to convert the shapes into compound paths before saving the SVG.

To automate the conversion of an SVG file to the VectorDrawable format you can use the on-line open source svg2android tool.

VectorDrawable support pre Android 5.0

While the VectorDrawable class is only available on 5.0+ at this stage, an unofficial project has released support for older versions of Android.

Visit Mr. Vector on GitHub for the source code and usage instructions. You should note that the Vector XML used in this project is slightly different to the standard VectorDrawable specification. You can convert your simple SVG files to the Mr. Vector format using Svg2MrVector.

UPDATE MAY 2015: VectorDrawableCompat is in the process of being developed and may be added to the official support library. Once released there is no need to use the Mr. Vector project anymore, so keep an eye on the official Android Developers Blog for updates to the support library.

References:

Scalable Vector Graphics http://en.wikipedia.org/wiki/Scalable_Vector_Graphics

SVG Path Format http://www.w3.org/TR/SVG11/paths.html#PathData

VectorDrawable https://developer.android.com/reference/android/graphics/drawable/VectorDrawable.html

MrVector https://github.com/telly/MrVector

Inkscape https://inkscape.org/

“NewTux” by Larry Ewing. Licensed under Attribution via Wikimedia Commons – http://commons.wikimedia.org/wiki/File:NewTux.svg#/media/File:NewTux.svg

“Flag of Ghana”. Licensed under Public Domain via Wikimedia Commons – http://commons.wikimedia.org/wiki/File:Flag_of_Ghana.svg

Advertisements

2 Comments

Filed under Android SDK, Image

Vector Graphics in Android: SVG Format

Vector graphics native support has long been on the wishlist of Android developers who have to export their vector graphics as a rasterized PNG file for each different device resolution.

The main use case for vector images are simple icons that need to scale to fit the resolution of the device. Another more complex use case is to implement functionality like that of the Androidify app from Google. In that app you can tweak and accessorize your little Android friend without any of the artifacts that become present when resizing raster images.

Why doesn’t Android support SVG?

I don’t believe there has ever been official word out of the Android team about support for SVG (Scalable Vector Graphics). However it is safe to assume that the reason SVG is not supported as a native image format is because of performance issues. SVG files can run into megabytes of XML data and to render a SVG those megabytes of XML have to be parsed and interpreted and then rasterized. Do some testing using some complex SVG images with some of the open source libraries in this article and you will see the performance issues that surface.

With Android 5.0 we have seen the future direction of vector graphics for the operating system, that is the VectorDrawable class. I will discuss this new functionality in more detail in a sequel to this article, but the take away from it is that full native SVG support will not be coming to Android any time soon, if ever. To read more about converting your SVG files to a VectorDrawable see the second part of this series on Vector Graphics in Android:

https://androidbycode.wordpress.com/2015/03/18/vector-graphics-in-android-converting-svg-to-vectordrawable/

Open Source SVG support

The solution for developers to get vector image support has been to turn to the open source community to fill this gap. There have been a few solid implementations providing SVG support in line with the majority of the SVG specification. However there is no prefect solution for using SVG files in Android and there never will be. Every implementation will have performance issues and, of what is currently available, they all have quirks (some would call bugs) that need to be worked around.

Here is a list of the main open source projects. None of these projects will support every SVG and none will support every part of the SVG specification. You will need to try each solution with the type of SVG files you want to render in your app.

AndroidSVG

Website: https://code.google.com/p/androidsvg/

Description: Parser and renderer for Android that claims almost complete support for the static visual elements of the SVG 1.1 and SVG 1.2 Tiny specifications.

Last release:  1.2.2-beta-1 (16 June 2014)

Known issues: 

  • Stroking of underlined or strike through text is not supported in versions of Android prior to 4.2
  • Android 4.3 bug that breaks the <clipPath> feature when using renderToPicture()
  • SVGImageView has documented issues in Android Studio

Status: Code is still being developed and a 1.3 release is planned although the last source code changes were checked in August 2014.

License: Apache License 2.0

Review: I had no issues with this library when rendering simple SVG files. Throw some complex SVGs at it and you see the performance hit you are taking. On some environments I was hitting the stack size limit and could not load some complex images. For my use case loading the SVG on a thread and displaying a placeholder image until completion of the load produced the most successful outcome.

svg-android

Website: https://github.com/pents90/svg-android/tree/master/svgandroid

Description:  The developers describe this as a compact and straightforward library for parsing SVG files and rendering them on an Android Canvas. This was the library used to render the interface of the original Androidify app.

Status: Appears abandoned, last changes 2012

License: View the license here

Summary: Very popular on initial release, there are many forks of this project but few have made substantial ongoing bug fixes. If this library works well for you except for some bugs then you may want to hunt around the many forks.

svg-android-2

Website: http://code.google.com/p/svg-android-2/

Description: Scalable Vector Graphics Support for Android. This project, a fork of the svg-android project, exists to provide additional capabilities to the svg-android project.

Status: Last code changes were Jan 2014, although very little active development takes place in this project, occasional bug fixes are applied.

License: Apache License 2.0

Summary: Fork of svg-android with enhanced features and newer bug fixes, however development is spasmodic.

TPSVG Android SVG Library

Website: https://github.com/TrevorPage/TPSVG_Android_SVG_Library

Description: SVG image parser for Android. The developers description is that it converts image to list of native android.graphics objects which can then be speedily rendered on Canvas, and provides callbacks to allow image elements to be manipulated programmatically.

Status: September 2013 was last activity on this project

License: Apache License 2.0

Commercial Support

There are some commercial options available for SVG support on Android. I have not tried them and have not read glowing reviews of them that would have me reaching for my wallet, if however any of them proved to have a performance edge loading SVG files then they may be worth your consideration.

Conclusion

SVG is a open standard that allows developers to quickly make p vector graphics without expensive software. However it is not a standard that was designed to be quickly rendered inside applications, which is why it is not supported by native Android. There are cases however where using SVG can not only save you development time, but also increase the visual appeal of an app.

If you believe your app falls into the category of those that can benefit using SVG then you may consider using one of the open source libraries. I would recommend AndroidSVG, as long as you follow my two golden rules with SVG and Android:

  • Keep the complexity of your SVG files to a minimum
  • Never load an SVG on the UI thread (either pre-load in advance, or display a placeholder while it is loading)

You may have to get your hands dirty and fix bugs yourself in any of these open source libraries, or work around bugs by manipulating the XML of your SVG files. It is best to have a variety of tools capable of writing SVG files as different tools will produce different XML that will perform differently with these libraries.

One last word of warning. Before you jump in and implement anything using the SVG format in your app you should take a look at VectorDrawables.  I won’t go into the pros and cons of these here, I will leave that for part 2 of this series on Vector images in Android.

Sample Project

For a functional sample showing the use of AndroidSVG, take a look at the following project from GitHub:

https://github.com/bmarrdev/CountryRank

References

SVG Homepage

http://www.w3.org/Graphics/SVG/

SVG Specification

http://www.w3.org/TR/SVG11/

Inkscape Open Source Vector Authoring Tool

https://inkscape.org/

Leave a comment

Filed under Android SDK, Image