Каковы наилучшие практики использования значков SVG на Android?

Я собираюсь создать свое первое Android родное (а не на основе браузера) приложение и искать некоторые хорошие практики в отношении создания/создания значков. Поскольку он должен поддерживать несколько устройств/разрешений, я думал, что лучше всего использовать SVG для их создания. Существует, по крайней мере, это lib: http://code.google.com/p/svg-android/, что promises предлагает поддержку SVG на Android.

До сих пор я не нашел ресурсов, описывающих использование этой или другой библиотеки в качестве средства для отображения значков SVG на устройстве, поэтому я немного неохотно использую его. Лучшее, что я видел до сих пор, - это использование SVG в качестве исходного формата для предварительного рендеринга значков на основе png в разных разрешениях.

Итак, мои вопросы: Являются ли значки SVG хорошим вариантом для непосредственного использования на устройстве без предварительного этапа рендеринга png (вообще-то он работает), и если, почему никто не использует этот подход?

Ответ 1

Для Android старше Lollipop ваша лучшая практика для SVG на Android будет заключаться в использовании инструмента для преобразования вашего SVG в PNG по интересующим вас размерам. Существующая поддержка SVG для Android не является исчерпывающей из того, что вы, вероятно, найдете в SVG файле, и даже если это так, поддержка не встроена в ОС, поэтому использование их непосредственно для значков, безусловно, отсутствует.

Начиная с Lollipop (API 21), см. Каковы наилучшие практики использования значков SVG на Android?. Спасибо @MarkWhitaker @AustynMahoney за указание на это.

Ответ 2

Начиная с Lollipop (API 21), Android определяет класс VectorDrawable для определения чертежей на основе векторной графики, Android Studio 1.4 добавляет "Векторный Asset Studio" , чтобы упростить их работу, включая функцию импорта SVG и новый плагин Gradle, который генерирует PNG-версии значков VectorDrawable во время сборки для API 20 и ранее. Там также сторонний инструмент для преобразования SVG в VectorDrawables. Имейте в виду, что хотя векторные чертежи могут быть определены в XML, формат файла не является SVG, и не все файлы SVG могут быть успешно преобразованы. Простая графика, например, значки, должна работать нормально.

Если вам все еще нужно самостоятельно создавать PNG, вам нужно будет сгенерировать ваши значки при различных разрешениях. Для упрощения создания этих PNG я создаю значки как SVG, а затем экспортирую в различные размеры, используя Inkscape, который является бесплатным и кросс-платформенным. Он получил несколько полезных функций для создания значков, включая представление Preview Preview (см. Ниже), и он генерирует хорошие четкие PNG.

enter image description here

Ответ 3

Это то, что мы используем для преобразования 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

Ответ 4

Хорошие новости всем! Поскольку поддержка андроида библиотека 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 вам нужно использовать атрибут app:srcCompat в ImageViews.
  • вы не можете использовать svg-s в StateListDrawables или других xml-чертежах, вместо этого создавайте их программно.
  • вы не можете использовать атрибут android:background или View.setBackgroundResource(), используйте вместо него View.setBackground().
  • вы не можете использовать svg-s в случае уведомлений.

Ответ 5

Другой вариант - преобразовать ваши объекты SVG в тип шрифта TTF. Включите шрифт в приложение и используйте его таким образом. Это делает трюк для монохромных простых форм.

Существует несколько бесплатных инструментов преобразования.

Ответ 6

Так как ответ nacho-coloma помог мне, я взял его отличный script и сделал его несколько проще в использовании на ежедневной основе.

Во-первых:

  • Создайте каталог drawable-svg рядом с вашим каталогом res.
  • Поместите ваши файлы svg и script в drawable-svg.
  • Сделайте исполняемый файл script.
  • Запустите его. В Ubuntu вы можете просто дважды щелкнуть его в Nautilus и сделать его запущенным в терминале.

И позже, когда вы получите новые файлы svg:

  1. Поместите новые svg файлы в drawable-svg и снова запустите script.

По умолчанию он будет делать то, что вы хотите: масштабируйте каждый файл svg в png файлах и поместите их в ../res/drawable-mdpi, ../res/drawable-hdpi и т.д.

script принимает два параметра:

  • Шаблон файла svg для масштабирования, по умолчанию: *.svg
  • Базовый каталог для put, по умолчанию ../res/ (т.е. ваш каталог res с указанной выше настройкой).

Вы можете поэкспериментировать, масштабируя один svg в pngs в текущем каталоге следующим образом:

$ ./svg2png test.svg .

Или просто обработать все изображения:

$ ./svg2png

Я думаю, вы могли бы разместить drawable-svg внутри каталога res, но я не заглянул в то, что обернуто в последнем APK. Кроме того, мои svg файлы имеют - в своих именах, что Android не нравится, а мой script заботится о переименовании png файлов на что-то действующее на Android.

Я использую ImageMagick для преобразования, которое немного более стандартно, чем Inkscape (хотя мне понравился подход). Оба метода включены в script для справки.

Здесь script:

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

Ответ 7

Android Support Library 23.2 Поддержка векторных чертежей и анимированных векторных чертежей

  • добавьте 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

Ответ 8

Значки SVG не являются хорошим вариантом для непосредственного использования на устройстве, если их нужно масштабировать до разных размеров, что обычно означает, что вы хотите использовать векторный формат в первую очередь. Большой значок никогда не будет масштабироваться изящно, потому что, ну, компьютерные дисплеи сделаны из пикселей. Таким образом, линии векторного изображения могут выравниваться "между пикселями", создавая размытую границу. Кроме того, большие значки требуют больше деталей, чем маленькие значки, которые нуждаются в очень немногих деталях. Детальный значок не очень хорош в очень малых размерах, и простой значок выглядит не очень хорошо при масштабировании в очень большие размеры. Я недавно прочитал замечательную статью об этом профессиональным дизайнером пользовательского интерфейса: Об этих векторных значках.

Ответ 9

Я только что разместил script для создания всех значков платформы для приложений PhoneGap, которые могут быть полезными. Однако добавить код для создания экранов.

Ответ 10

Я только начал использовать Victor, библиотеку с открытым исходным кодом от Trello, для преобразования SVG файлов в PNG файлы различных требуемых разрешения во время сборки.

ПРОФИ

  • Вам не нужно запускать script или инструмент для создания различных файлов PNG при каждом изменении или добавлении значка. (Вам нужно нажать Rebuild в Android Studio, когда вы добавили новый файл svg или переименовали существующий).
  • Нет PNG в вашем источнике, поэтому там меньше помех.

СВОД

  • Единственный недостаток, который я видел до сих пор, заключается в том, что Android Studio еще не распознает генерируемые ресурсы в XML, поэтому вы получите красные предупреждения в ваших XML файлах, и у вас нет автозаполнения для ваших чертежей на основе SVG, Он прекрасно работает, и эта проблема должна быть исправлена ​​в будущей версии Android Studio.

Если вы используете SVG, сгенерированный http://materialdesignicons.com/, обязательно загрузите весь файл или скопируйте с вкладки "Файл SVG" при выборе "Просмотр SVG"

Ответ 11

Мне никогда не удавалось запускать сценарии оболочки Linux в Cygwin в Windows. Итак, вот пакетный файл, который делает то, что делает Nacho Coloma bash script. Небольшое различие заключается в том, что этот командный файл требует как ввода, так и имени выходного файла, как в "svg2png -w24 input.svg output.png".

Настройте папку "svg" в каталоге проекта src/main и скопируйте файлы SVG и этот пакетный файл в эту папку в соответствии с инструкциями Stephan. Запустите пакетный файл из папки 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

Ответ 12

svg является удивительным. кто хочет использовать svg:

щелкните правой кнопкой мыши на drawable "new/Vector Asset", выберите "значок материала" для значков по умолчанию и "файл SVG локали" для вашего файла на жестком диске вашего компьютера и в имени типа "имя ресурса" для файла svg, затем нажмите "next" и "finish"

и вы можете использовать это в 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>