¿Cuáles son las mejores prácticas para usar iconos SVG en Android?

I am about to create my first Android nativo (so not browser based) app and looking for some good practices regarding icon creating/provisioning. Since it should support multiple devices/resolutions I thought it is best to use SVG to create them. There is at least this lib: http://code.google.com/p/svg-android/ that promises to offer support for SVG on Android.

So far, I have not found resources describing the usage of this or another library as a means to render SVG Icons on the device, so I am a bit reluctant in using it. The best I have seen so far is using SVG as the source format for pre-rendering png based icons in different resolutions.

So my questions is: Are SVG icons a good option to use directly on the device without a png pre-rendering step (does it work at all), and if, why does nobody seem to use this approach?

preguntado el 10 de marzo de 12 a las 15:03

12 Respuestas

From Lollipop (API 21) onwards, Android defines the VectorDibujable class, for defining drawables based on vector graphics. Android Studio 1.4 adds the "Vector Asset Studio" to make them easier to work with, including an SVG import feature and a new Gradle plugin that generates PNG versions of VectorDrawable icons at build time for API 20 and earlier. There's also a third-party tool for converting SVGs to VectorDrawables. Bear in mind that although vector drawables can be defined in XML, the file format is not SVG and not all SVG files can be successfully converted. Simple graphics like icons should work OK.

If you still need to generate PNGs yourself, you'll need to generate your icons at various resolutions. For ease of generating those PNGs I design icons as SVG and then export to the various sizes using Inkscape which is free and cross-platform. It's got some nice features for designing icons, including the Icon Preview view (see below), and it generates nice crisp PNGs.

enter image description here

Respondido el 14 de enero de 16 a las 10:01

Unfortunately the SVG Import function is very, very basic. - petirrojo

The Android team has released backwards compatibility support for Vector Assets in Android Studio 1.4. I have updated the answer to reflect this. android-developers.blogspot.com/2015/09/android-studio-14.html - austyn mahoney

tutorial link is missing/leading to this page - V-master

For Android older than Lollipop, your best practice for SVG on Android is going to be to use a tool to convert your SVG to PNG at the size(s) you're interested in. Existing SVG support for Android is not comprehensive of what you're likely to find in an SVG file, and even if it were, the support is not built into the OS so using them directly for icons is definitely out.

Beginning with Lollipop (API 21) see ¿Cuáles son las mejores prácticas para usar iconos SVG en Android?. Thanks to @MarkWhitaker @AustynMahoney for pointing this out.

contestado el 23 de mayo de 17 a las 13:05

Androidify uses this library and it looks quite comprehensive. The lib seems to be able to produce Pictures and Drawables. Would it be possible to use this to create a custom icon class leveraging this? - user462982

If the icon you're referring to is what shows up in the launcher, no. Android doesn't allow you to specify a method to generate the icon, it only permits you to identify the icon by its resource. - mah

If the library you're working with can process the SVGs you have well, you can make it work for buttons but not through the standard Android API; you'll need to create a custom button view. Around 12-18 months ago I used the library you linked and at that time it had trouble with many SVGs I had created in Inkscape or downloaded from various places. Perhaps its support has improved since then, but I recommend testing it with the exact SVGs you plan to use before you write a lot of custom code for it. - mah

This answer is definitely not correct now. stackoverflow.com/a/29229005/116938 - austyn mahoney

respuesta obsoleta - Bendecido

This is what we are using to transform a SVG file into multiple resolutions. For example, to generate the launch icon: svg2png -w48 icon.svg

#!/bin/bash -e
# Transforms a SVG into a PNG for each platform
# Sizes extracted from
# http://developer.android.com/design/style/iconography.html

[ -z $2 ] && echo -e "ERROR: filename and one dimension (-w or -h) is required, for example:\nsvg2png -w48 icon.svg\n" && exit 1;
DEST_FILENAME=`echo $2 | sed s/\.svg/\.png/`
FLAG=`echo $1 | cut -c1-2`
ORIGINAL_VALUE=`echo $1 | cut -c3-`

if [ "$FLAG" != "-w" ] && [ "$FLAG" != "-h" ]; then
    echo "Unknown parameter: $FLAG" 
    exit 1

# PARAMETERS: {multiplier} {destination folder}
function export {
  VALUE=$(echo "scale=0; $ORIGINAL_VALUE*$1" | bc -l)
  CMD="inkscape $FLAG$VALUE --export-background-opacity=0 --export-png=src/main/res/$2/$DEST_FILENAME src/main/svg/$FILENAME > /dev/null"
  echo $CMD
  eval $CMD

export 1 drawable-mdpi
export 1.5 drawable-hdpi
export 2 drawable-xhdpi
export 3 drawable-xxhdpi
export 4 drawable-xxxhdpi

Respondido 11 Abr '14, 15:04

Good to know, nice script, very useful. I can avoid importing SVGs into GIMP or PS. I think you should add some tips about how to use it (it fails if the folders don't exist). - jc

Good news everyone! Since android support biblioteca 23.2 we can use svg-s till back to Nivel de API 7!

If you wanna be compatible backwards only till Lollipop (API 21) check Mark Whitaker's answer, but if you want to go below you need to add these lines to your build.gradle:

// Gradle Plugin 2.0+ (if you using older version check the library announcement link)
android {  
    defaultConfig {  
        vectorDrawables.useSupportLibrary = true  

También tenga en cuenta que:

  • en lugar de android:src necesitas usar el app:srcCompat attribute in ImageViews.
  • you cannot use svg-s in StateListDrawables or other xml drawables, create them programmatically instead.
  • no puedes usar el android:background atributo o View.setBackgroundResource() función, utilice la View.setBackground() preferiblemente.
  • you cannot use svg-s in case of Notifications.

contestado el 23 de mayo de 17 a las 12:05

I've done this, but i only see the svg on devices with api level > 21. what is wrong here? - Morteza Rastgoo

Are you using color attributes in you svg? could you create a new question and insert the svg and your build.gradle file there? - Bendecido

@Morteza check this answer also, if it's still not working at you: stackoverflow.com/a/36661438/3162918 - Bendecido

Como nacho-coloma's answer helped me, I've taken his excellent script and made it slightly easier to use on a daily basis.


  1. Crear directorio drawable-svg junto a tu res directorio.
  2. Place your svg files and this script in drawable-svg.
  3. Haga que el script sea ejecutable.
  4. Run it. In Ubuntu you can simply double-click it in Nautilus and make it run in a terminal.

And later when you get new svg files:

  1. Place new svg files in drawable-svg y vuelva a ejecutar el script.

By default it will do what you want: Scale every svg file into png files and put them into ../res/drawable-mdpi, ../res/drawable-hdpi etc.

El script toma dos parámetros:

  1. The svg file pattern to scale, default: *.svg
  2. The base directory for put, default ../res/ (es decir, tu res directory with the above mentioned setup).

You can experiment by scaling a single svg into pngs in the current directory like this:

$ ./svg2png test.svg .

Or simply process all images:

$ ./svg2png

I guess you could place the drawable-svg inside the res directory, but I haven't looked into what gets wrapped up in the final APK. Also, my svg files have - in their names, which Android doesn't like, and my script takes care of renaming the png files to something valid on Android.

I'm using ImageMagick for the conversion which is slightly more standard that Inkscape (though I liked the approach). Both methods are included in the script for reference.

Aquí está el guión:


scalesvg ()

    svgwidthxheight=$(identify "$svgfile" | cut -d ' ' -f 3)

    pngfile="$(basename $svgfile)" # Strip path.
    pngfile="${pngfile/.svg/.png}" # Replace extension.
    pngfile="${pngfile/[^A-Za-z0-9._]/_}" # Replace invalid characters.
    pngfile="$pngdir/$qualifier/$pngfile" # Prepend output path.

    if [ ! -d $(dirname "$pngfile") ]; then
        echo "WARNING: Output directory does not exist: $(dirname "$pngfile")"
        #echo "Exiting"
        #exit 1
        echo "Outputting here instead: $pngfile"

    pngwidth=$(echo "scale=0; $svgwidth*$pngscale" | bc -l)
    pngheight=$(echo "scale=0; $svgheight*$pngscale" | bc -l)
    pngdensity=$(echo "scale=0; 72*$pngscale" | bc -l) # 72 is default, 

    echo "$svgfile ${svgwidth}×${svgheight}px -> $pngfile ${pngwidth}×${pngheight}px @ $pngdensity dpi"

    convert -background transparent -density $pngdensity "$svgfile" "$pngfile"
    #inkscape -w${pngwidth} --export-background-opacity=0 --export-png="$pngfile" "$svgfile" > /dev/null
    #convert "$svgfile" -background transparent -scale ${pngwidth}x${pngheight} "$pngfile"

svgfiles="${svgfiles:=*.svg}" # Default to input all *.svg in current dir.

pngdir="${pngdir:=../res}" # Default to place output pngs to ../res, ie. ../res/drawable-hdpi etc.

for svgfile in $svgfiles; do
    echo "Scaling $svgfile ..."
    scalesvg "$svgfile" "$pngdir" 0.75 drawable-ldpi
    scalesvg "$svgfile" "$pngdir" 1    drawable-mdpi
    scalesvg "$svgfile" "$pngdir" 1.5  drawable-hdpi
    scalesvg "$svgfile" "$pngdir" 2    drawable-xhdpi
    scalesvg "$svgfile" "$pngdir" 3    drawable-xxhdpi
    scalesvg "$svgfile" "$pngdir" 4    drawable-xxxhdpi

echo -n "Done."
read # I've made it wait for Enter -- convenient when run from Nautilus.

contestado el 11 de mayo de 16 a las 15:05

Another option is to convert your SVG assets into TTF font type. Include the font on your app and use it that way. This does the trick for monochromatic simple shapes.

There are several free conversion tools.

Respondido el 02 de diciembre de 15 a las 21:12

Android Support Library 23.2 Support Vector Drawables and Animated Vector Drawables

  1. add vectorDrawables.useSupportLibrary = true to your build.gradle file.
  2. Utilizan app:srcCompat="@drawable/ic_add" en lugar de android:src="..." or setImageResource() for your ImageView


Respondido 27 Jul 16, 11:07

I've done this, but i only see the svg on devices with api level > 21. what is wrong here? - Morteza Rastgoo

@MortezaRastgoo Could you please show your code somewhere? I can't guess without it. It works well for me. - lordmegamax

SVG icons are not a good option to use directly on a device if they need to be scaled to many different sizes, which is usually why you'd want to use vector format in the first place. A large icon will never scale down gracefully because, well, computer displays are made out of pixels. So the lines of the vector image may get aligned "in between pixels", creating a blurry border. Moreover, large icons need more details than small icons, which need very few details. A detailed icon does not look good in very small size, and a simple icon does not look good when scaled into very large size. I recently read an excellent article on this by a professional UI designer: About those vector icons.

Respondido 21 Abr '12, 22:04

You can control those things to a certain extent with shape-rendering. Support is sparse, though. - Joey

Thanks @Joey, that's good to know. However, even that doesn't allow you to specify that an element should be dropped altogether if the image is rendered as small enough. - Cero uno

Random thing that I just thought of: The varying icon sizes in apps are usually due to different pixel densities of the target device – thus they all appear at roughly the same visual size. Thus they actually no need to be more or less detailed depending on the size. At least not in this context. I'm currently using SVG as source format for icons in two Android apps at work and the only thing you podría need to pay attention to is aligning edges to pixel boundaries for the baseline size (mdpi). Android also suggests that icons use at least two pixels for lines at baseline size. - Joey

I'm using Inkscape to render them in the necessary resolutions; since our artist draws vector icons anyway that's the easiest approach. It also allows to generate color of opacity variations on the fly (e.g. enabled/disabled icon pairs), which is a enorme benefit of SVG. The difference when downscaling the largest PNG is small, but subtly visible (the edges are not exactamente as crisp because you're downscaling the antialiasing as well). - Joey

You would only need one version for extra-low resolutions and one for all others. vs what, 5-6 different bitmaps you have to provide for Android right now? Besides, why limit supported image formats: let the usuario decide what format they prefer. - velis

I've just posted a script for generating all the platform icons for PhoneGap apps that may be of value. Yet to add code for generating screens.

Respondido 28 ago 14, 03:08

Acabo de empezar a usar Víctor, an open source library by Trello, to convert SVG files to PNG files of the various required resolutions during build time.


  • You won't have to run a script or tool to create various PNG files every time you change or add an icon. (You do need to hit Rebuild in Android Studio when you've added a new svg file or renamed an existing one)
  • No PNG's in your source, so there's less clutter.


  • The only downside I've seen so far is that Android Studio doesn't yet recognize generated resources in XML, so you'll get some red warnings in your XML files and you don't have autocomplete for your SVG based drawables. It builds fine though, and this issue should be fixed in a future version of Android Studio.

If you use SVG generated by http://materialdesignicons.com/ be sure to either download the whole file, or copy from the 'SVG File'-tab when choosing 'View SVG'

Respondido 23 Jul 15, 14:07

svg is awesome. who want use svg:

right click on drawable "new/Vector Asset" choose "material icon" for default icons and "locale SVG file" for your file in your computer hard drive and in "resource name" type name for svg file then click on "next" button and "finish"

and you can use that in drawable. fillcolor must be hard code.

ejemplo simple


<vector xmlns:android="http://schemas.android.com/apk/res/android"

Respondido el 14 de enero de 16 a las 17:01

I've never had much luck running Linux shell scripts in Cygwin on Windows. So here is a batch file that does what Nacho Coloma's bash script does. One small difference, is that this batch file requires both an input and an output file name, as in "svg2png -w24 input.svg output.png".

Set up an "svg" folder in your project's src/main directory and copy your SVG files and this batch file to that folder, per Stephan's instructions. Run the batch file from the svg folder. If you're on 32-bit Windows, then you will likely need to change the path to Inkscape to use "Program Files (x86)".

@echo off
echo Convert an SVG file to a PNG resource file with multiple resolutions.

rem Check the arguments
set temp=%1
set switch=%temp:~0,2%
set pixels=%temp:~2%
if not "%switch%"=="-w" (
if not "%switch%"=="-h" (
echo Error:  Invalid image width or height switch.  Use -w or -h, with target image size in dp appended.
goto :error
echo %pixels%| findstr /r /c:"^[1-9][0-9]*$" >nul
if errorlevel 1 (
echo Error:  Invalid numeric image size.  Image size must be a positive integer.
goto :error
if "%3"=="" (
echo Error:  Not enough arguments.
goto :error
if not "%4"=="" (
echo Error:  Too many arguments.
goto :error

call :export %1 %2 %3 mdpi
call :export %1 %2 %3 hdpi
call :export %1 %2 %3 xhdpi
call :export %1 %2 %3 xxhdpi
call :export %1 %2 %3 xxxhdpi
exit /b

rem parameters: <width/height> <input-file> <output-file> <density>

set temp=%1
set switch=%temp:~0,2%
set pixels=%temp:~2%

if %4==mdpi set /a size=%pixels%
if %4==hdpi set /a size=%pixels%*3/2
if %4==xhdpi set /a size=%pixels%*2
if %4==xxhdpi set /a size=%pixels%*3
if %4==xxxhdpi set /a size=%pixels%*4

echo %size% pixels ../res/drawable-%4/%3
"C:\Program Files\Inkscape\inkscape.exe" %switch%%size% --export-background-opacity=0 --export-png=../res/drawable-%4/%3 %2
exit /b

echo Synopsis: svg2png -w^<width-pixels^>^|-h^<height-pixels^> ^<input-file^> ^<output-file^>
echo Example:  svg2png -w24 "wifi white.svg" wifi_connect_24dp.png
exit /b

Respondido 09 Oct 15, 00:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.