我即将创建我的第一个Android 原生(因此不是基于浏览器的)应用,并寻找有关图标创建/配置的一些良好做法。 由于它应该支持多个设备/分辨率,我认为最好使用SVG来创建它们。至少有这个lib:http://code.google.com/p/svg-android/承诺在Android上提供对SVG的支持。
到目前为止,我还没有找到描述使用此库或其他库的资源作为在设备上呈现SVG图标的方法,所以我有点不愿意使用它。到目前为止,我见过的最好的是使用SVG作为预渲染基于png的图标的源格式。
所以我的问题是:SVG图标是不是在没有png预渲染步骤的情况下直接在设备上使用的好选项(它是否可以工作),如果,为什么似乎没有人使用这种方法?
答案 0 :(得分:42)
从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。
答案 1 :(得分:31)
这是我们用来将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
答案 2 :(得分:26)
对于比Lollipop更早的Android,您在Android上使用SVG的最佳做法是使用工具将您的SVG转换为您感兴趣的大小的PNG。现有的Android SVG支持并不全面您可能在SVG文件中找到的内容,即使是这样,操作系统中也没有内置支持,因此直接将它们用于图标肯定是不存在的。
从Lollipop(API 21)开始,请参阅What are best practices for using SVG icons on Android?。感谢@MarkWhitaker @AustynMahoney指出这一点。
答案 3 :(得分:15)
大家好消息!由于android支持library 23.2,我们可以使用svg-s直到回到 API级别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
属性。 android:background
属性或View.setBackgroundResource()
功能,请改用View.setBackground()
。答案 4 :(得分:8)
由于 nacho-coloma 的回答对我有所帮助,我采用了他出色的剧本,使其每天使用起来更容易。
首先:
drawable-svg
目录旁边创建目录res
。drawable-svg
。稍后当你获得新的svg文件时:
drawable-svg
并再次运行脚本。默认情况下,它会执行您想要的操作:将每个svg文件扩展为png文件并将其放入../res/drawable-mdpi
,../res/drawable-hdpi
等。
该脚本有两个参数:
*.svg
../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.
答案 5 :(得分:6)
另一种选择是将SVG资产转换为TTF字体类型。在您的应用中包含该字体并以这种方式使用它。这就是单色简单形状的技巧。
有几种免费的转换工具。
答案 6 :(得分:5)
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 :(得分:3)
SVG图标不是直接在设备上使用的好选项,如果它们需要缩放到许多不同的大小,这通常是你想要首先使用矢量格式的原因。大图标永远不会正常缩小,因为计算机显示器是由像素组成的。因此,矢量图像的线可以“在像素之间”对齐,从而产生模糊的边界。此外,大图标需要比小图标更多的细节,小图标需要很少的细节。在非常小的尺寸上,详细的图标看起来不太好,当缩放到非常大的尺寸时,简单的图标看起来不太好。我最近阅读了一篇由专业UI设计师撰写的优秀文章:About those vector icons。
答案 8 :(得分:2)
我刚发布了一个脚本,用于生成可能有价值的PhoneGap应用的所有平台图标。然而,要添加用于生成屏幕的代码。
答案 9 :(得分:2)
我刚刚开始使用Trello的开源库Victor,在构建期间将SVG文件转换为各种所需分辨率的PNG文件。
赞成
CONS
如果您使用http://materialdesignicons.com/生成的SVG,请务必下载整个文件,或者在选择“查看SVG”时从“SVG文件”标签中复制
答案 10 :(得分: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
答案 11 :(得分:0)
svg太棒了。 谁想要使用svg:
右键单击drawable“new / Vector Asset”,为您的计算机硬盘驱动器中的文件选择“material icon”作为默认图标和“locale SVG file”,然后在svg文件的“resource name”类型名称中选择,然后单击“下一个“按钮和”完成“
你可以在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>