首页 文章

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

提问于
浏览
66

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

到目前为止,我还没有找到描述这个或另一个库的使用的资源作为在设备上呈现SVG图标的方法,所以我有点不愿意使用它 . 到目前为止,我所看到的最好的是使用SVG作为在不同分辨率下预渲染基于png的图标的源格式 .

所以我的问题是:SVG图标是一个很好的选择,可以直接在设备上使用而无需png预渲染步骤(它是否可以工作),如果,为什么似乎没有人使用这种方法?

12 回答

  • 25

    对于比Lollipop更早的Android,你在Android上使用SVG的最佳做法是使用工具将SVG转换为你感兴趣的大小的PNG . 现有的Android支持SVG并不全面 . '很可能在SVG文件中找到,即使它是,但是支持不是内置在操作系统中,因此直接使用它们来获取图标肯定是不合适的 .

    从Lollipop(API 21)开始,请参阅What are best practices for using SVG icons on Android? . 感谢@MarkWhitaker @AustynMahoney指出这一点 .

  • 15

    从Lollipop(API 21)开始,Android定义了VectorDrawable类,用于根据矢量图形定义drawable . Android Studio 1.4 adds the "Vector Asset Studio"使它们更易于使用,包括SVG导入功能和新的Gradle插件,可在构建时为API 20及更早版本生成VectorGrawable图标的PNG版本 . 还有a third-party tool for converting SVGs to VectorDrawables . 请记住,尽管可以使用XML定义矢量drawable,但文件格式不是SVG,并且不能成功转换所有SVG文件 . 像图标这样的简单图形应该可以 .

    如果您仍需要自己生成PNG,则需要生成图标at various resolutions . 为了便于生成这些PNG,我将图标设计为SVG,然后使用Inkscape导出到各种大小,这是免费的跨平台 . 它有一些很好的设计图标功能,包括图标预览视图(见下文),它可以生成漂亮的清晰PNG .

    enter image description here

  • 6

    这就是我们用来将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
    
  • 31

    大家好消息!由于android支持library 23.2我们可以使用svg-s直到 API level 7

    如果你想向后兼容直到Lollipop(API 21)检查Mark Whitaker's回答,但如果你想要进入下面,你需要将这些行添加到你的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,而是以编程方式创建它们 .

    • 您无法使用 android:background 属性或 View.setBackgroundResource() 函数,请改用 View.setBackground() .

    • 如果是通知,则不能使用svg-s .

  • 5

    nacho-coloma 's answer helped me, I'采取了他的优秀剧本,使其每天使用起来更容易一些 .

    第一:

    • res 目录旁边创建目录 drawable-svg .

    • 将您的svg文件和此脚本放在 drawable-svg 中 .

    • 使脚本可执行 .

    • 运行它 . 在Ubuntu中,您只需在Nautilus中双击它并使其在终端中运行即可 .

    以后当你得到新的svg文件时:

    • 将新的svg文件放在 drawable-svg 中并再次运行该脚本 .

    默认情况下,它会执行您想要的操作:将每个svg文件扩展为png文件并将它们放入 ../res/drawable-mdpi../res/drawable-hdpi 等 .

    该脚本有两个参数:

    • 要扩展的svg文件模式,默认值: *.svg

    • put的基本目录,默认 ../res/ (即具有上述设置的 res 目录) .

    您可以通过将单个svg缩放到当前目录中的png来进行实验,如下所示:

    $ ./svg2png test.svg .
    

    或者只是处理所有图像:

    $ ./svg2png
    

    我想你可以将 drawable-svg 放在res目录中,但是我还没有查看最终APK中包含的内容 . 另外,我的svg文件名称中有 - ,Android不喜欢,我的脚本负责将png文件重命名为Android上有效的文件 .

    我正在使用ImageMagick进行转换,这稍微更标准一些Inkscape(虽然我喜欢这种方法) . 这两种方法都包含在脚本中以供参考 .

    这是脚本:

    #!/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.
    
  • 3

    另一种选择是将SVG资产转换为TTF字体类型 . 在您的应用中包含该字体并以这种方式使用它 . 这就是单色简单形状的技巧 .

    有几种免费的转换工具 .

  • 2

    Android支持库23.2支持向量Drawables和动画矢量Drawables

    • vectorDrawables.useSupportLibrary = true 添加到build.gradle文件中 .

    • 使用 app:srcCompat="@drawable/ic_add" 代替 android:src="..."setImageResource() 用于ImageView

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

  • 7

    SVG图标不是直接在设备上使用的好选项,如果它们需要缩放到许多不同的大小,这通常是你想要首先使用矢量格式的原因 . 大图标永远不会正常缩小,因为计算机显示器是由像素组成的 . 因此矢量图像的线条可能会对齐"in between pixels",从而产生模糊的边框 . 此外,大图标需要比小图标更多的细节,小图标需要很少的细节 . 在非常小的尺寸上,详细的图标看起来不太好,当缩放到非常大的尺寸时,简单的图标看起来不太好 . 我最近阅读了一篇由专业UI设计师撰写的精彩文章:About those vector icons .

  • 2

    我刚刚发布了一个脚本,用于生成可能有 Value 的PhoneGap应用程序的所有平台图标 . 然而,要添加用于生成屏幕的代码 .

  • 39

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

    PROS

    • 您赢了'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'已添加新的svg文件或重命名现有文件

    • 没有PNG 's in your source, so there' s杂乱 .

    缺点

    • 我唯一的缺点是_1771064尚未识别XML中生成的资源,因此您可以为基于SVG的drawables自动完成 . 它构建得很好,这个问题应该在Android Studio的未来版本中修复 .

    如果您使用http://materialdesignicons.com/生成的SVG,请务必下载整个文件,或者在选择'View SVG'时从'SVG File' -tab复制

  • 0

    我在Windows上运行Cygwin中的Linux shell脚本时从来没有太多运气 . 所以这是一个批处理文件,它可以完成Nacho Coloma的bash脚本所做的工作 . 一个小的区别是,此批处理文件需要输入和输出文件名,如“svg2png -w24 input.svg output.png”中所示 .

    在项目的src / main目录中设置“svg”文件夹,并根据Stephan的说明将SVG文件和此批处理文件复制到该文件夹 . 从svg文件夹运行批处理文件 . 如果您使用的是32位Windows,则可能需要更改Inkscape的路径以使用“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
    
  • 0

    svg太棒了 . 谁想要使用svg:

    右键单击drawable“new / Vector Asset”为您的计算机硬盘驱动器中的文件选择“material icon”作为默认图标和“locale SVG file”,在svg文件的“resource name”类型名称中单击“next”按钮和“完成”

    你可以在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>
    

相关问题