web-dev-qa-db-fra.com

Quelles sont les meilleures pratiques pour utiliser les icônes SVG sur Android?

Je suis sur le point de créer ma première application Android ) native (donc non basée sur un navigateur) et à la recherche de bonnes pratiques concernant: icône création/mise en service. Puisqu'il devrait supporter plusieurs périphériques/résolutions, j'ai pensé qu'il était préférable d'utiliser SVG pour les créer. Il existe au moins cette lib: http://code.google.com/p/svg- Android / qui promet d’offrir une prise en charge de SVG sur Android.

Jusqu'à présent, je n'ai pas trouvé de ressources décrivant l'utilisation de cette bibliothèque ou d'une autre comme moyen de rendre des icônes SVG sur le périphérique. Je suis donc un peu réticent à l'utiliser. Le meilleur que j'ai vu jusqu'à présent utilise SVG comme format source pour les icônes basées sur le png avant le rendu dans différentes résolutions.

Ma question est donc la suivante: les icônes SVG sont-elles une bonne option à utiliser directement sur le périphérique sans étape préalable au rendu du png (fonctionne-t-il du tout), et si, pourquoi personne ne semble-t-il utiliser cette approche?

71
user462982

Pour Android plus ancien que Lollipop, votre meilleure pratique pour le SVG sur Android va être d'utiliser un outil pour convertir votre SVG en PNG à la taille (s. ) Le support SVG existant pour Android n’est pas exhaustif et ne contient pas tout ce que vous pourriez trouver dans un fichier SVG. Même s’il s’agissait d’un tel support, le support n’est pas intégré à la OS donc les utiliser directement pour les icônes est définitivement sorti.

Commençant par Lollipop (API 21), voir Quelles sont les meilleures pratiques pour l’utilisation des icônes SVG sur Android? . Merci à @MarkWhitaker @AustynMahoney pour l'avoir signalé.

26
mah

À partir de Lollipop (API 21), Android définit le VectorDrawable classe, pour définir Dessins basés sur des graphiques vectoriels. Android Studio 1.4 ajoute "Vector Asset Studio" pour faciliter son travail, y compris une fonctionnalité d'importation SVG et un nouveau plugin Gradle qui génère des versions PNG des icônes VectorDrawable à la compilation. Il est également n outil tiers permettant de convertir des SVG en VectorDrawables . N'oubliez pas que, bien que les fichiers vectoriels puissent être définis en XML, le format de fichier n'est pas SVG ni tout SVG. les fichiers peuvent être convertis avec succès. Les graphiques simples tels que les icônes devraient fonctionner correctement.

Si vous devez toujours générer vous-même des fichiers PNG, vous devez générer vos icônes à différentes résolutions . Pour faciliter la génération de ces PNG, je conçois des icônes au format SVG, puis exporte vers les différentes tailles à l’aide de Inkscape , logiciel gratuit et multiplate-forme. Il possède quelques fonctionnalités intéressantes pour la conception d’icônes, notamment la vue Aperçu des icônes (voir ci-dessous), et génère de jolis PNG nets.

enter image description here

42
Mark Whitaker

C'est ce que nous utilisons pour transformer un fichier SVG en plusieurs résolutions. Par exemple, pour générer l’icône de lancement: 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
Nacho Coloma

Bonnes nouvelles tout le monde! Depuis Android support bibliothèque 23.2 nous pouvons utiliser svg-s jusqu’au retour à niveau de l’API 7 !

Si vous voulez être compatible en amont seulement jusqu'à ce que Lollipop (API 21) coche la réponse Mark Whitaker , mais si vous voulez aller en dessous, vous devez ajouter ces lignes à votre build.gradle:

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

Gardez également à l'esprit que:

  • au lieu de Android:src, vous devez utiliser l'attribut app:srcCompat dans ImageViews.
  • vous ne pouvez pas utiliser svg-s dans StateListDrawables ou dans d’autres dessinables XML, créez-les plutôt par programme.
  • vous ne pouvez pas utiliser l'attribut Android:background ni la fonction View.setBackgroundResource(), utilisez plutôt la fonction View.setBackground().
  • vous ne pouvez pas utiliser svg-s en cas de notifications.
15
bendaf

Depuis que la réponse de nacho-coloma m'a aidé, j'ai repris son excellent script et l'ai légèrement simplifiée à utiliser au quotidien.

Première:

  1. Créer un répertoire drawable-svg à côté de votre répertoire res.
  2. Placez vos fichiers svg et ce script dans drawable-svg.
  3. Rendre le script exécutable.
  4. Exécuter. Dans Ubuntu, vous pouvez simplement double-cliquer dessus dans Nautilus et le faire fonctionner dans un terminal.

Et plus tard, quand vous aurez de nouveaux fichiers svg:

  1. Placez les nouveaux fichiers svg dans drawable-svg et relancez le script.

Par défaut, il fera ce que vous voulez: mettez tous les fichiers svg à l’échelle et placez-les dans ../res/drawable-mdpi, ../res/drawable-hdpi etc.

Le script prend deux paramètres:

  1. Le modèle de fichier svg à mettre à l'échelle, par défaut: *.svg
  2. Le répertoire de base pour put, par défaut ../res/ _ (c’est-à-dire votre répertoire res avec la configuration susmentionnée).

Vous pouvez expérimenter en mettant à l'échelle un seul svg en pngs dans le répertoire en cours de la manière suivante:

$ ./svg2png test.svg .

Ou simplement traiter toutes les images:

$ ./svg2png

Je suppose que vous pourriez placer le drawable-svg dans le répertoire res, mais je n’ai pas cherché à savoir ce qui se trouve dans le fichier APK final. De plus, mes fichiers svg ont - _ dans leurs noms, ce qui Android n'aime pas, et mon script prend en charge de renommer les fichiers png en quelque chose de valide sur Android.

J'utilise ImageMagick pour la conversion, ce qui est légèrement plus standard qu'Inkscape (même si j'ai bien aimé l'approche). Les deux méthodes sont incluses dans le script pour référence.

Voici le 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.
8

Une autre option consiste à convertir vos ressources SVG en type de police TTF. Incluez la police dans votre application et utilisez-la de cette façon. Cela fait l'affaire pour les formes simples monochromes.

Il existe plusieurs outils de conversion gratuits.

6
Chepech

Bibliothèque de support Android 23.2 Dessins vectoriels de support et Dessins vectoriels d'animation

  1. ajoutez vectorDrawables.useSupportLibrary = true à votre fichier build.gradle.
  2. Utilisez app:srcCompat="@drawable/ic_add" Au lieu de Android:src="..." Ou setImageResource() pour votre ImageView

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

5
lordmegamax

Les icônes SVG ne sont pas une bonne option à utiliser directement sur un périphérique si elles doivent être redimensionnées de différentes tailles, ce qui est généralement la raison pour laquelle vous souhaitez utiliser le format vectoriel. Une grande icône ne sera jamais réduite avec élégance, car les écrans d’ordinateur sont en pixels. Ainsi, les lignes de l'image vectorielle peuvent être alignées "entre pixels", créant une bordure floue. De plus, les grandes icônes nécessitent davantage de détails que les petites, qui nécessitent très peu de détails. Une icône détaillée n'a pas l'air bien dans une très petite taille, et une simple icône n'a pas l'air bien lorsqu'elle est réduite à une très grande taille. J'ai récemment lu un excellent article sur ce sujet par un concepteur d'interface utilisateur professionnel: À propos de ces icônes vectorielles .

3
ZeroOne

Je viens de poster un script pour générer toutes les icônes de plate-forme pour les applications PhoneGap qui pourraient être utiles. Encore à ajouter du code pour générer des écrans.

2
Tony O'Hagan

Je viens juste de commencer à utiliser Victor , une bibliothèque open source de Trello, pour convertir les fichiers SVG en fichiers PNG des différentes résolutions requises pendant la phase de construction.

AVANTAGES

  • Vous n'avez pas besoin d'exécuter un script ou un outil pour créer divers fichiers PNG chaque fois que vous modifiez ou ajoutez une icône. (Vous devez appuyer sur Reconstruire dans Android Studio lorsque vous avez ajouté un nouveau fichier svg ou renommé un fichier existant).
  • Pas de PNG dans votre source, donc moins d'encombrement.

LES INCONVÉNIENTS

  • Le seul inconvénient que j’ai vu jusqu’à présent est que Android Studio ne reconnaît pas encore les ressources générées en XML; vous obtiendrez donc des avertissements rouges dans vos fichiers XML sans que vous n’ayez La saisie semi-automatique pour vos tirables basés sur SVG est très bien construite, et ce problème devrait être résolu dans une future version de Android Studio.

Si vous utilisez SVG généré par http://materialdesignicons.com/ , veillez à télécharger tout le fichier ou à le copier depuis l'onglet "Fichier SVG" lorsque vous choisissez "Afficher SVG".

2
Ciske Boekelo

Je n'ai jamais eu beaucoup de chance d'utiliser des scripts Linux Shell dans Cygwin sous Windows. Voici donc un fichier de commandes qui fait ce que fait le script bash de Nacho Coloma. Une petite différence est que ce fichier de commandes requiert à la fois une entrée et un nom de fichier de sortie, comme dans "svg2png -w24 input.svg output.png".

Configurez un dossier "svg" dans le répertoire src/main de votre projet et copiez vos fichiers SVG et ce fichier de commandes dans ce dossier, conformément aux instructions de Stephan. Exécutez le fichier de commandes à partir du dossier svg. Si vous utilisez Windows 32 bits, vous devrez probablement modifier le chemin d'accès à Inkscape pour qu'il utilise "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
Linda X

svg est génial. qui veulent utiliser svg:

cliquez avec le bouton droit de la souris sur "nouvelle ressource/vecteur", choisissez "icône de matériau" pour les icônes par défaut et "fichier SVG de langue locale" pour votre fichier sur le disque dur de votre ordinateur et dans "nom de la ressource", tapez le nom du fichier svg puis cliquez sur le bouton "Suivant". et fini"

et vous pouvez l'utiliser dans drawable. La couleur de remplissage doit être un code dur.

exemple simple

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
mehrdad khosravi