Які найкращі практики використання піктограм SVG на Android?


75

Я збираюся створити свій перший рідний додаток для Android (отже, не на основі браузера) і шукатиму кілька практичних методів створення / надання іконок. Оскільки він повинен підтримувати кілька пристроїв / роздільної здатності, я вважав, що найкраще використовувати SVG для їх створення. Існує принаймні ця бібліотека: http://code.google.com/p/svg-android/, яка обіцяє запропонувати підтримку SVG на Android.

Поки що я не знайшов ресурсів, що описують використання тієї чи іншої бібліотеки як засобу для відображення піктограм SVG на пристрої, тому я трохи неохоче використовую її. Найкраще, що я бачив досі, - це використання SVG як вихідного формату для попереднього відтворення піктограм на основі png у різних роздільних здатностях.

Тож мої запитання: чи є піктограми SVG хорошим варіантом для використання безпосередньо на пристрої без кроку попереднього візуалізації png (чи працює це взагалі), і якщо, чому, здається, ніхто не використовує цей підхід?

Відповіді:


30

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

Починаючи з Lollipop (API 21), див. Які найкращі практики використання піктограм SVG на Android? . Дякую @MarkWhitaker @AustynMahoney за те, що на це вказує.


1
Androidify використовує цю бібліотеку, і вона виглядає досить повною. Схоже, lib може створювати зображення та малюнки. Чи можна було б використовувати це для створення власного класу значків, використовуючи це?
user462982

Якщо піктограма, на яку ви посилаєтесь, відображається в панелі запуску, ні. Android не дозволяє вказати метод генерації піктограми, він дозволяє лише ідентифікувати піктограму за її ресурсом.
mah

1
Якщо бібліотека, з якою ви працюєте, може добре обробляти ваші SVG-файли, ви можете зробити так, щоб вона працювала для кнопок, але не за допомогою стандартного Android API; вам потрібно буде створити власний перегляд кнопок. Близько 12-18 місяців тому я користувався бібліотекою, яку ви зв’язали, і на той момент вона мала проблеми із багатьма SVG-файлами, які я створив у Inkscape або завантажив з різних місць. Можливо, з тих пір його підтримка покращилася, але я рекомендую протестувати її з точними SVG, які ви плануєте використовувати, перш ніж писати для неї багато власного коду.
mah

2
Ця відповідь зараз точно не правильна. stackoverflow.com/a/29229005/116938
Austyn Махоні

1
застаріла відповідь
bendaf

47

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

Якщо вам все-таки потрібно самостійно створювати PNG-файли, вам потрібно буде створювати свої значки з різною роздільною здатністю . Для зручності створення цих PNG я розробляю піктограми у форматі SVG, а потім експортую в різні розміри за допомогою Inkscape, який є безкоштовним і крос-платформним. У ньому є кілька приємних функцій для проектування піктограм, включаючи подання попереднього перегляду піктограм (див. Нижче), і він створює приємні чіткі PNG-файли.

введіть тут опис зображення


2
На жаль, функція імпорту SVG дуже і дуже проста.
Робін

2
Команда Android випустила підтримку зворотної сумісності Vector Assets в Android Studio 1.4. Я оновив відповідь, щоб відобразити це. android-developers.blogspot.com/2015/09/android-studio-14.html
Остін Махоні,

посилання на підручник відсутнє / веде до цієї сторінки
V-master

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

Корисно знати, приємний сценарій, дуже корисний. Я можу уникнути імпорту SVG у GIMP або PS. Думаю, вам слід додати кілька порад щодо того, як ним користуватися (це не вдається, якщо папок не існує).
jc

16

Всім гарних новин! Оскільки бібліотека підтримки Android 23.2 може використовувати SVG-S до повернення до рівня API 7 !

Якщо ви хочете бути сумісним назад лише до льодяника (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 у разі сповіщень.

Я зробив це, але бачу svg лише на пристроях з рівнем api> 21. що тут не так?
Morteza Rastgoo

1
Чи використовуєте ви атрибути кольору у своєму svg? не могли б ви створити нове запитання та вставити туди svg та свій файл build.gradle?
bendaf

1
@Morteza перевірити цю відповідь також, якщо він ще не працює на вас: stackoverflow.com/a/36661438/3162918
bendaf

8

Оскільки відповідь nacho-coloma мені допомогла, я взяв його чудовий сценарій і полегшив його використання щодня.

Спочатку:

  1. Створіть каталог drawable-svgбіля вашого resкаталогу.
  2. Розмістіть свої файли svg та цей скрипт у drawable-svg.
  3. Зробіть сценарій виконуваним.
  4. Запусти його. В Ubuntu ви можете просто двічі клацнути на ньому в Nautilus і зробити так, щоб він працював у терміналі.

А пізніше, коли ви отримуєте нові файли svg:

  1. Помістіть нові файли svg drawable-svgта запустіть сценарій знову.

За замовчуванням він буде робити те , що ви хочете: масштабування кожного файлу SVG в дитячі файли і помістити їх в ../res/drawable-mdpi, і ../res/drawable-hdpiт.д.

Сценарій приймає два параметри:

  1. Шаблон файлу svg для масштабування, за замовчуванням: *.svg
  2. Базовий каталог для 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.

6

Іншим варіантом є перетворення ваших SVG-ресурсів у тип шрифту TTF. Включіть шрифт у свій додаток і використовуйте його таким чином. Це робить фокус для однотонних простих форм.

Існує кілька безкоштовних інструментів перетворення.


5

Бібліотека підтримки Android 23.2 Підтримка векторних малюнків та анімованих векторних малюнків

  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 лише на пристроях з рівнем api> 21. що тут не так?
Morteza Rastgoo

@MortezaRastgoo Не могли б ви десь показати свій код? Без цього не здогадуюсь. Для мене це добре працює.
lordmegamax

3

Піктограми SVG не є гарним варіантом для використання безпосередньо на пристрої, якщо їх потрібно масштабувати до багатьох різних розмірів, саме тому, як правило, спочатку потрібно використовувати векторний формат. Велика піктограма ніколи не зменшиться витончено, оскільки, ну, комп'ютерні дисплеї зроблені з пікселів. Тож лінії векторного зображення можуть вирівнюватися "між пікселями", створюючи розмиту межу. Більше того, великі піктограми потребують більше деталей, ніж маленькі піктограми, яким потрібно дуже мало деталей. Детальна піктограма виглядає не дуже добре в дуже малих розмірах, а проста ікона не виглядає добре, якщо її масштабують у дуже великі розміри. Нещодавно я прочитав чудову статтю про це професійного дизайнера інтерфейсу: Про ці векторні іконки .


Ви можете певною мірою керувати цими речами за допомогою shape-rendering. Однак підтримка скупа.
Джої,

Дякую @Joey, це добре знати. Однак навіть це не дозволяє вказати, що елемент слід взагалі скинути, якщо зображення відображається як досить маленьке.
ZeroOne

4
Випадкова річ, про яку я тільки що подумав: Різні розміри піктограм у програмах, як правило, зумовлені різною щільністю пікселів цільового пристрою - отже, всі вони мають приблизно однаковий візуальний розмір. Таким чином, їм насправді не потрібно бути більш-менш детальними залежно від розміру. Принаймні не в цьому контексті. Зараз я використовую SVG як вихідний формат для значків у двох робочих програмах Android, і єдине, на що вам, можливо, доведеться звернути увагу, це вирівнювання країв до меж пікселів для розміру базової лінії (mdpi). Android також пропонує, щоб піктограми використовували принаймні два пікселі для ліній базового розміру.
Джої

1
Я використовую Inkscape для надання їх у необхідних роздільних здатностях; оскільки наш художник у будь-якому випадку малює векторні іконки, це найпростіший підхід. Це також дозволяє генерувати кольорові зміни непрозорості на льоту (наприклад, пари значків увімкнено / вимкнено), що є величезною перевагою SVG. Різниця при зменшенні масштабу найбільшого PNG невелика, але помітно помітна (краї не зовсім чіткі, тому що ви також зменшуєте масштаб згладжування).
Джої

1
Вам потрібна буде лише одна версія для наднизького дозволу та одна для всіх інших. проти чого, 5-6 різних растрових зображень, які ви повинні надати для Android прямо зараз? Крім того, навіщо обмежувати підтримувані формати зображень: нехай користувач вирішує, який формат він віддає перевагу.
Веліс


2

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

Плюси

  • Вам не доведеться запускати сценарій або інструмент для створення різних файлів PNG щоразу, коли ви змінюєте або додаєте піктограму. (Вам потрібно натиснути кнопку Відновити в Android Studio, коли ви додали новий файл svg або перейменували наявний)
  • У вашому джерелі немає файлів PNG, тому безлад буде менше.

ПРОТИВ

  • Єдиним недоліком, який я бачив дотепер, є те, що Android Studio ще не розпізнає згенеровані ресурси у XML, тому ви отримаєте червоні попередження у своїх XML-файлах, і у вас немає автозавершення для ваших графічних матеріалів на основі SVG. Однак він добре працює, і цю проблему слід виправити в майбутній версії Android Studio.

Якщо ви використовуєте SVG, згенерований http://materialdesignicons.com/, не забудьте або завантажити весь файл, або скопіювати з вкладки "Файл SVG", вибравши "Перегляд SVG"


1

svg - це чудово. хто хоче використовувати svg:

клацніть правою кнопкою миші на "new / Vector Asset", що малюється, виберіть "піктограму матеріалу" для піктограм за замовчуванням і "SVG файл локалі" для вашого файлу на жорсткому диску вашого комп'ютера та в "Ім'я ресурсу" введіть ім'я для файлу svg, потім натисніть кнопку "Далі" і "закінчити"

і ви можете використовувати це в розводному. 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>

0

Мені ніколи не пощастило запустити сценарії оболонки Linux в Cygwin в Windows. Отже, ось командний файл, який виконує те, що робить скрипт bas Nacho Coloma. Одна невелика відмінність полягає в тому, що для цього командного файлу потрібні і вхідне, і вихідне ім'я файлу, як у "svg2png -w24 input.svg output.png".

Налаштуйте папку "svg" у директорії src / main вашого проекту та скопіюйте у неї SVG-файли та цей пакетний файл відповідно до інструкцій Стефана. Запустіть командний файл із папки svg. Якщо ви використовуєте 32-розрядну Windows, то вам, ймовірно, доведеться змінити шлях до Inkscape, щоб використовувати "Програмні файли (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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.