For quite a long time, we have been developing children's applications for Android, gradually grasping the many nuances of this platform. There is one rake that lurks us in each application - this is the fragmentation of screens. If you make one image just for a small phone, then on the tablet it looks to put it mildly “not very”. And if you make a high-resolution image for tablets and try to use it on phones, then with a very high probability the application will fall out with OutOfMemory.
We have to prepare several copies of the same image for different screens. Even more cloud thickens new monster Galaxy Nexus 10 with an insane resolution of 2560x1600.

')
In general, it would be nice to change something, we decided. And what if you use in applications not raster images, and vector? Such images are easily scaled for different screen resolutions, while not losing quality. You can use just one image for different resolutions and sizes.
No sooner said than done. So, under the cut, the history of introducing vector images into one of our applications. In the article we will share the experience and features of using vector images in SVG format in Android applications.
A little googling found out that vector images for web and applications are usually used in SVG format. With this format work vector editors Adobe Illustrator and Inkscape. Armed with Inkscape, cut the test images and began to look for ways to download and display them in the Android application.
I didn’t want to deal with the SVG format device and write my own parser - most likely, people came across this before us! Well, we google "android svg".
The result is:
We take the most popular - SVG-Android (by the way, he moved to Github, but there are no new commits there). We connect the library, put the vector image in res / raw, load it and set it into the view:
SVG svg = SVGParser.getSVGFromResource(getResources(), R.raw.filename); Drawable drawable = svg.createPictureDrawable(); imageView.setImageDrawable(drawable);
We load the test project with images - everything is fine! We connect our images - empty. As it turned out, this library supports only SVG basic 1.1 format, which is not supported by Inkspace, but is born only in Adobe Illustrator.
We try the second library of SVG-Android-2, which is a fork of the first project and went a little further.
She already understands Inkscape, and also supports other chips of this format, which you can read about
here . Here everything went easier, the pictures were loaded and looked gorgeous on the phone and on the tablet. We stayed on it.
An example of an SVG image and a non-adapted PNG image for a tablet on a tablet.
(view image in original size
1280x800 )
The first is SVG (10 Kb), the second is PNG (22 Kb). The second image has a blurred outline and a stepped gradient.Image scaling
Images are scaled only with preservation of proportions. Therefore, using them as a background, which may slightly change the proportions at different resolutions, will not work. In this case, we usually make some abstract image in PNG, which changes its proportions quite easily for different screens.
Do not forget for SVG to set the adjustViewBounds property to true, otherwise the image may not count its boundaries in the way you intended.
Image size with shadows and highlights
Some elements in our application were originally drawn with small shadows and backlights - for example, this emoticon has a gray backlight. But this leads to a huge increase in the size of the SVG file. 118 Kb against 1 Kb without this highlight. The larger the file size, the more time it takes to load it in the program, so we decided to abandon this effect.
Images with and without shadow: 118 Kb vs 1 KbThe backlight can be turned off either in the graphic editor, or by direct editing of the SVG file - we delete the <image /> tag with a huge content.
Gradient mapping
Some images suddenly showed black spots instead of the background. It turned out that the gradient is not supported!
The problem with gradients was solved by removing the extra tags from svg (described later in the article). But in principle, it would be possible to live with this and in our simple images to replace the gradient with a uniform fill, if it were not for another nuance - considerable loading time of images.
Here is how it looked on the screen: on the left - the black sky in the form of a gradient, on the right - the correct picture.

Image upload time
The application needed 6 images per ViewPager page, and since they are loaded during the scrolling process (if not cached), the interface jerks noticeably when scrolling. I really didn’t want this, and it was decided to download all the images at the start of the application. Got an initialization time of about 8 seconds, which was too long.
The problem decided to understand. Pumped out the source code of the project SVG-Android-2 and began to look for what is so slow. It turned out that in the SVGParser class, the XML image file is parsed
twice : the first time it collects information about the additional attributes that are used during the second pass. And, most interestingly, only the xlink: href attribute is analyzed, which is some semblance of hyperlinks within the document itself. In our problem images there were just such links, and they led nowhere. After we got rid of these links by editing the SVG code in some images, the gradient began to display correctly. Moreover, by removing this preliminary pass and optimizing the loading process a bit, we were able to reduce the download speed from 8 seconds to 1.8-2. It should be noted that this is commensurate with a medium-size PNG - it took 1.7 seconds to load the same images into memory.
Below is a comparison of downloading 35 files in the format of SVG and PNG.
| Svg | PNG (~ 500x500) |
Size, KB | 327 | 943 |
Load time, with | 1.9 | 1.7 |
Transparency and color filters
Often in games we use translucent images for inactive elements. In this project, in addition to transparency, we needed color filters to generate elements in games, that is, so that one element could be used once, but by painting it differently, we would get different elements.
It turned out that neither alpha nor colorFilter we can not apply, because the library loads not the typical bitmapDrawable, but the pictureDrawable, and in the Android sources, we see empty methods for this class:
@Override public void setColorFilter(ColorFilter colorFilter) {} @Override public void setAlpha(int alpha) {}
Before this, the pictureDrawable class has never been encountered, and it was a big surprise.
Having again rummaged through the library sources, we found in the SVGHandler class the fillPaint field of type Paint, which draws all the components. If you set a colorFilter to it before loading the item, it will work as expected. We were quite satisfied with this, so we slightly changed the method of loading SVG, adding the ability to transfer the color of the filter there, which if necessary is set before the image is loaded. Now the images were loaded like this:
SVG svg = SVGParser.getSVGFromResource(getResources(), rawSvgId, filterColor);
And in the very SVGHandler appeared this method:
public void setFilterColor(int filterColor) { fillPaint.setColorFilter(new PorterDuffColorFilter(filterColor, Mode.MULTIPLY)); }
As a result, we were able to get as many images of different shades as possible from one image.

You can also set Alpha for fillPaint, but in games this property is required in a dynamic form (clicked on the element - it became translucent), and it is inconvenient to load a new image each time. Therefore, this effect was replaced by scaling (clicked - the element decreased).
Nuance with forced processing of the GPU
After launching the application, we began to receive such errors:
java.lang.UnsupportedOperationException at android.view.GLES20Canvas.drawPicture(GLES20Canvas.java:895) at android.graphics.drawable.PictureDrawable.draw(PictureDrawable.java:73)
It turned out that if the “Forced GPU processing” setting is enabled on the device (Developer options - Force GPU Rendering), then our application crashes, because Canvas's drawPicture () method does not support hardware acceleration. You can read about it on
android developer .
And the simple indication in the manifest android: hardwareAccelerated = "false" does not solve the problem - the user tick in the settings has a higher priority.
A fairly simple solution was found: for all views that work with our pictureDrawable, obtained from SVG, disable hardware acceleration.
Since the hardware acceleration function appeared in Android 3.0 (api 11), in order to work with this functionality, we had to change the target sdk of our project from 8 to 11. And, of course, we need to remember about backward compatibility - there are no these methods on earlier platforms.
public static void setSoftwareLayerType(View view) { try { view.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } catch (NoSuchMethodError e) {
findings
Let's summarize the work with vector images in the SVG format in Android.
Pros:
- One huge plus from which all others follow is one vector image .
- Since the picture is a vector image, it is perfectly displayed on all screen sizes.
- The size of the SVG images is small.
- One picture is used several times for different resolutions.
- Reduces the process of preparing images for the application.
Minuses:
- Pictures are scaled only proportionally.
- Transparency is not supported.
- The graphics should be simplified - the more vector elements, the more the file weighs. It is undesirable to use shadows and glows, as this increases the size of SVG files by several times.
As a result of experiments with SVG, an application for children “Learn forms and shapes” was born. You can view the application on Google Play:
play.google.com/store/apps/details?id=com.whisperarts.kids.formsThe number of resulting images:
- PNG - 3 (splashscreen and 2 backgrounds for the menu);
- SVG elements - 97;
- Application size 3.5 MB.
In comparison with our “Learning Colors” application, which is almost similar in functionality (8 MB in size), there is a gain of more than 50%.
For ourselves, we made the decision to use SVG images in our applications, since this significantly speeds up the process of developing and adapting images for different screen resolutions, and also significantly reduces the weight of the application.
We hope that the experience we shared in the article will help you to review the process of preparing images for applications and to think about using the SVG format.
PS: If you have already used SVG in your projects or otherwise avoided the problems we encountered when using SVG - write in the comments. Looking forward to hearing your experience.