在Android上使用SVG图标的最佳做法是什么?

我即将创build我的第一个Android 本地 (所以不是基于浏览器的)应用程序,并寻找一些关于图标创build/供应的良好做法。 由于它应该支持多种设备/分辨率,我认为最好使用SVG来创build它们。 至less有这个lib: http : //code.google.com/p/svg-android/ ,它承诺在Android上提供对SVG的支持。

到目前为止,我还没有find描述这个或另一个库的用法的资源作为在设备上呈现SVG图标的手段,所以我有点不情愿使用它。 到目前为止,我所见过的最好的方法是使用SVG作为以不同分辨率预渲染基于PNG的图标的源格式。

所以我的问题是:SVG图标是不使用PNG预渲染步骤直接在设备上使用的好select(它是否工作),以及为什么没有人使用这种方法?

对于Lollipop之前的Android,Android上的SVG最佳实践将是使用工具将SVG转换为您感兴趣的大小的PNG。现有的SVG对Android的支持并不全面很可能在SVG文件中find,即使是这样,支持也没有内置到操作系统中,所以直接将它们用于图标是绝对没有的。

从棒棒糖(API 21)开始,请参阅在Android上使用SVG图标的最佳做法是什么? 。 感谢@MarkWhitaker @AustynMahoney指出这一点。

从棒棒糖(API 21)开始,Android定义了VectorDrawable类,用于定义基于vectorgraphics的drawable。 Android Studio 1.4添加了“Vector Asset Studio” ,使其更容易使用,包括SVG导入function和新的Gradle插件,可在构build时为API 20及更早版本生成VectorDrawable图标的PNG版本。 还有一个将SVG转换为VectorDrawables的第三方工具 。 请记住,尽pipe可以使用XML定义vector绘图,但文件格式不是SVG,并非所有的SVG文件都可以成功转换。 简单的图标像图标应该可以。

如果您仍然需要自己生成PNG,则需要以各种分辨率生成图标。 为了便于生成这些PNG,我将图标devise为SVG,然后使用免费且跨平台的Inkscape将其导出为各种大小。 它有一些很好的function来devise图标,包括图标预览视图(见下面),它生成漂亮的PNG。

在这里输入图像说明

这是我们正在使用将SVG文件转换成多个分辨率。 例如,要生成启动图标: 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; FILENAME=$2 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 fi # 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 

大家好消息! 由于Android支持库23.2,我们可以使用svg-s直到回到API级别7

如果你想只在Lollipop(API 21)检查马克·惠特克的答案时才向后兼容,但是如果你想下面去,你需要添加这些行到你的build.gradle:

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

另外请记住:

  • 而不是android:src你需要在ImageViews中使用app:srcCompat属性。
  • 你不能在StateListDrawables或其他xml drawables中使用svg-s,而是以编程方式创build它们。
  • 您不能使用android:background属性或View.setBackgroundResource()函数,请改用View.setBackground()
  • 在通知的情况下你不能使用svg-s。

另一种select是将您的SVG资产转换为TTF字体types。 在您的应用程序中包含字体并以此方式使用。 这是单色简单形状的伎俩。

有几个免费的转换工具。

由于纳乔 – 科洛马的答案帮助了我,我已经采取了他的优秀剧本,并且使其日常使用更容易一些。

第一:

  1. res目录旁边创build目录drawable-svg
  2. 把你的svg文件和这个脚本放在drawable-svg
  3. 使脚本可执行。
  4. 运行。 在Ubuntu中,只需在Nautilus中双击它并使其在terminal中运行即可。

而后来当你得到新的SVG文件:

  1. 将新的svg文件放在drawable-svg ,然后再次运行脚本。

默认情况下,它会做你想做的:缩放每个SVG文件到PNG文件,并把它们放入../res/drawable-hdpi等。

该脚本需要两个参数:

  1. 要缩放的svg文件模式,默认: *.svg
  2. 放置的基础目录,默认../res/ res ../res/ (即您的res目录与上面提到的设置)。

您可以通过在当前目录中缩放单个svg到pngs来进行试验,如下所示:

 $ ./svg2png test.svg . 

或者简单地处理所有图像:

 $ ./svg2png 

我想你可以把drawable-svg放在res目录中,但是我没有看到在最后的APK中包含了什么。 此外,我的svg文件的名称中有哪些Android不喜欢,我的脚本负责将png文件重命名为Android上的有效内容。

我正在使用ImageMagick进行转换,它比Inkscape稍微更标准(尽pipe我喜欢这种方法)。 这两种方法都包含在脚本中供参考。

这是脚本:

 #!/bin/bash scalesvg () { svgfile="$1" pngdir="$2" pngscale="$3" qualifier="$4" svgwidthxheight=$(identify "$svgfile" | cut -d ' ' -f 3) svgwidth=${svgwidthxheight%x*} svgheight=${svgwidthxheight#*x} 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" pngfile="$qualifier-${svgfile/.svg/.png}" fi 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="$1" svgfiles="${svgfiles:=*.svg}" # Default to input all *.svg in current dir. pngdir="$2" 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 done echo -n "Done." read # I've made it wait for Enter -- convenient when run from Nautilus. 

Android支持库23.2支持vector绘图和animationvector绘图

  1. vectorDrawables.useSupportLibrary = true添加到您的build.gradle文件中。
  2. 使用app:srcCompat="@drawable/ic_add"而不是android:src="..."setImageResource()为ImageView

http://android-developers.blogspot.sk/2016/02/android-support-library-232.html

如果需要将SVG图标缩放到许多不同的大小,SVG图标不是直接在设备上使用的好select,这通常是为什么您首先要使用vector格式。 一个大图标永远不会正常缩放,因为计算机显示器是由像素构成的。 因此,vector图像的线条可能会在“像素之间”alignment,从而产生模糊的边框。 而且,大图标比小图标需要更多的细节,这些图标只需要很less的细节。 一个细小的图标在尺寸上看起来不太好,而当缩放到非常大的尺寸时,一个简单的图标看起来不太好。 我最近阅读了一个专业的UIdevise师关于这个优秀的文章: 关于这些vector图标 。

我刚刚发布了一个脚本,用于为PhoneGap应用程序生成所有可能有价值的平台图标。 但是要添加代码来生成屏幕。

我刚刚开始使用Trello的开源库Victor ,在构build时将SVG文件转换为各种所需分辨率的PNG文件。

PROS

  • 每次更改或添加图标时,都不必运行脚本或工具来创build各种PNG文件。 (当你添加一个新的svg文件或重新命名一个现有的文件时,你需要在Android Studio中打开重build)
  • 没有PNG在你的来源,所以有更less的混乱。

缺点

  • 到目前为止,唯一的缺点是Android Studio尚不能识别XML中生成的资源,所以在XML文件中会出现一些红色的警告,而且您的SVG基于drawable没有自动完成function。 它虽然构build得很好,但这个问题应该在Android Studio的未来版本中得到修复。

如果您使用http://materialdesignicons.com/生成的SVG,请务必下载整个文件,或者在select“查看SVG”时从“SVG文件”;

在Windows上的Cygwin中,我从来没有运行过Linux shell脚本。 所以这里是一个batch file,可以做Nacho Coloma的bash脚本。 一个小的区别是,这个batch file需要input和输出文件名,如“svg2png -w24 input.svg output.png”中所示。

在项目的src / main目录下build立一个“svg”文件夹,按照Stephan的说明将SVG文件和这个batch file复制到该文件夹​​中。 从svg文件夹运行batch file。 如果您使用的是32位Windows,则可能需要更改Inkscape的path才能使用“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 :export 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 :error 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 

SVG是真棒。 谁想要使用svg:

右键单击可绘制的“新build/vector资产”select“材料图标”为默认图标和“语言环境SVG文件”为您的文件在您的计算机硬盘驱动器和“资源名称”types名称为SVG文件,然后单击“下一步”button和“完成”

你可以使用drawable。 fillcolor必须是硬编码。

简单的例子

navigation_toggle.xml

 <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:fillColor="#FFFFFF" android:pathData="M3,18h18v-2H3v2zm0,-5h18v-2H3v2zm0,-7v2h18V6H3z"/> </vector>