I Vector Drawable (VD) all’interno degli applicativi Android

Oggi vi parlerò dell’utilizzo dei Vector Drawable (VD) all’interno degli applicativi Android. Dalla versione 23.2 è stata garantita la retro compatibilità di questo formato con le versioni più vecchie e questo ha reso il loro utilizzo quasi indispensabile per la creazione delle animazioni e delle immagini.

Iniziamo prendendo in esempio il seguente VD (immagine 1):

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:viewportWidth="200"
        android:viewportHeight="200"
        android:width="200px"
        android:height="200px">
    <group android:name="android">
        <path
            android:name="square"
        android:fillColor="#FFFF"
        android:pathData="M100,100l100,0l0,100l-100,0z"/>
</group>
    </vector>

1.Esempio di percorso chiuso descritto da un Vector Drawable

Procedendo dall’interno verso l’esterno troviamo:

  • Il path: ovvero il singolo elemento di un’immagine; all’interno di un VD possono essercene diversi e possono essere divisi in group. Il parametro fondamentale è pathData, che contiene il percorso chiuso dei punti che definisce l’oggetto.
  • Il group (opzionale): permette di “giocare” con gli elementi al suo interno senza andare a modificare gli elementi che non vi appartengono. Questo risulta molto importante per le animazioni.
  • Il vector: è l’elemento base; i parametri viewport Width-Height definiscono l’area di lavoro, width-height definiscono la grandezza standard dell’elemento.

                                                                                                                      

Il pathData è a tutti gli effetti un SVG i cui comandi sono scritti in sequenza, troviamo in questa pagina una descrizione delle funzioni disponibili https://www.w3.org/TR/SVG11/paths.html#PathData.

Il disegno di un pathData può essere pensato come una penna che si sposta su un foglio bianco. Nel nostro esempio troviamo all’interno del pathData i comandi:

  • Mx,y che inizia un path partendo dal punto di coordinate x,y
  • lx,y che disegna una linea dal punto attuale a quello finale spostandosi del valore assegnato alle variabili x e y
  • z ha il compito di chiudere il percorso descritto dalle istruzioni precedenti

 

Altri campi che si trovano all’interno del pathData sopra descritto sono il fillColor, che definisce il colore di riempimento, e il campo name che è di fondamentale importanza per gli aspetti più avanzati riguardanti l’animazione dei VD.

Descritti i punti essenziali di un VD, prendiamone in esame uno più complesso che descrive il classico robottino di Android:

<?xml version="1.0" encoding="utf-8"?>

<vector xmlns:android="http://schemas.android.com/apk/res/android"

    android:viewportWidth="500"

    android:viewportHeight="500"

    android:width="500px"

    android:height="500px">

    <group android:name="android">

        <group android:name="head_eyes">

            <path

                android:name="head"

                android:fillColor="#9FBF3B"

                android:pathData="M301.314,83.298l20.159-29.272c1.197-1.74,0.899-4.024-0.666-5.104c-1.563-1.074-3.805-0.543-4.993,1.199L294.863,80.53c-13.807-5.439-29.139-8.47-45.299-8.47c-16.16,0-31.496,3.028-45.302,8.47l-20.948-30.41c-1.201-1.74-3.439-2.273-5.003-1.199c-1.564,1.077-1.861,3.362-0.664,5.104l20.166,29.272c-32.063,14.916-54.548,43.26-57.413,76.34h218.316C355.861,126.557,333.375,98.214,301.314,83.298" />

            <path

                android:name="left_eye"

                android:fillColor="#FFFFFF"

                android:pathData="M203.956,129.438c-6.673,0-12.08-5.407-12.08-12.079c0-6.671,5.404-12.08,12.08-12.08c6.668,0,12.073,5.407,12.073,12.08C216.03,124.03,210.624,129.438,203.956,129.438" />

            <path

                android:name="right_eye"

                android:fillColor="#FFFFFF"

                android:pathData="M295.161,129.438c-6.668,0-12.074-5.407-12.074-12.079c0-6.673,5.406-12.08,12.074-12.08c6.675,0,12.079,5.409,12.079,12.08C307.24,124.03,301.834,129.438,295.161,129.438" />

        </group>

        <group android:name="arms">

            <path

                android:name="left_arm"

                android:fillColor="#9FBF3B"

                android:pathData="M126.383,297.598c0,13.45-10.904,24.354-24.355,24.354l0,0c-13.45,0-24.354-10.904-24.354-24.354V199.09c0-13.45,10.904-24.354,24.354-24.354l0,0c13.451,0,24.355,10.904,24.355,24.354V297.598z" />

            <path

                android:name="right_arm"

                android:fillColor="#9FBF3B"

                android:pathData="M372.734,297.598c0,13.45,10.903,24.354,24.354,24.354l0,0c13.45,0,24.354-10.904,24.354-24.354V199.09c0-13.45-10.904-24.354-24.354-24.354l0,0c-13.451,0-24.354,10.904-24.354,24.354V297.598z" />

        </group>

        <path

            android:name="body"

            android:fillColor="#9FBF3B"

            android:pathData="M140.396,175.489v177.915c0,10.566,8.566,19.133,19.135,19.133h22.633v54.744c0,13.451,10.903,24.354,24.354,24.354c13.451,0,24.355-10.903,24.355-24.354v-54.744h37.371v54.744c0,13.451,10.902,24.354,24.354,24.354s24.354-10.903,24.354-24.354v-54.744h22.633c10.569,0,19.137-8.562,19.137-19.133V175.489H140.396z" />
   </group>
</vector>

Come si può subito notare, sono definiti più group e ad ognuno è stato dato un nome con l’obbiettivo di muovere ogni gruppo separatamente.

Il movimento è possibile tramite l’utilizzo di un ulteriore XML che descrive un Animated Vector Drawable (AVD):

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
                 android:drawable="@drawable/android">

    <target
        android:animation="@animator/shrug"
        android:name="head_eyes" />

    <target
        android:animation="@animator/shrug"
        android:name="arms" />
</animated-vector>

Il VD utilizzato è definito attraverso il campo drawable (in questo caso si tratta del robottino descritto sopra) e sono definiti dei target che applicano un’animazione ad un singolo group o path del VD. In questo caso è stato usato "@animator/shrug" il cui codice viene riportato qui di seguito:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="translateY"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="-10"
        android:repeatMode="reverse"
        android:repeatCount="infinite"
        android:duration="250" />
</set>

L’objectAnimator è un tag le cui proprietà definiscono il tipo di animazione che verrà applicata al group o path associato.

Inserita questa AVD in un’ImageView basta accedere al drawable e iniziare l’animazione per ottenere un robottino che ride:

Drawable drawable = androidImageView.getDrawable();

        if (drawable instanceof Animatable) {

            ((Animatable) drawable).start();

        }

Questi esempi possono sembrare banali, ma con un po’ di inventiva possono essere creati degli effetti gradevoli con poche righe di codice. Per avere un’idea su possibili casi d’uso consiglio i seguenti link: http://userinterfaces.io/, http://useyourinterface.com/.

Queste mie riflessioni prendono spunto dalla conferenza di Mark Allison al Mobiconf 2016 tenutosi a Cracovia, per ulteriori informazioni vi consiglio di seguire il suo blog a questo indirizzo https://blog.stylingandroid.com/

 

Alessandro Oddo
mobile developer

 

Pubblicato in Tutorial da Giorgia