DevCorner: una panoramica sui Layout

Giuseppe Tripodi
Giuseppe Tripodi Tech Master
DevCorner: una panoramica sui Layout

Se avete mai creato app per Android, vi sarete certamente scontrati almeno una volta con la bestia nera di tutti i programmatori che, specialmente sul nostro robottino, può dare parecchio filo da torcere: l'interfaccia grafica. Su Android, nello specifico, gestire correttamente le dimensioni e il posizionamento degli elementi può essere veramente una grande rogna. Quindi, sebbene per imparare a muoversi correttamente non c'è miglior tutorial che l'esperienza, questa settimana diamo un po' di linee guida per muovere i primi passi con i layout.

Partendo dalle basi, saprete certamente che i layout per le nostre Activity si trovano all'interno della cartella res/layout e, per convenzione, il nome di ognuna di esse dovrebbe corrispondere a quello dell'attività di riferimento, con l'eccezione che, invece del CamelCase, si usa dividere le parole con un underscore( _ ) e, soprattutto, scrivere tutto in minuscolo per evitare problemi col file R.java.

Il formato utilizzato è l'XML e, nonostante il framework Android offra la possibilità di fare drag&drop degli elementi grafici, spessissimo vi troverete a metter mano al codice dell'interfaccia.

È possibile utilizzare diversi layout di base, ognuno con le proprie peculiarità, diverse a seconda dell'utilizzo che se ne deve fare: sebbene l'elenco sia relativamente lungo (10 elementi appaiono sotto la voce Layout) e alcuni di essi abbiano anche una certa importanza (vedi GridLayout e TableLayout), quelli che utilizzerete più spesso e che è bene conoscere a fondo sono certamente il LinearLayout e il RelativeLayout.

LinearLayout

Per quanto riguarda il primo dei due, si tratta di un particolare tipo di Layout che può essere utilizzato in orizzontale o verticale: l'orientamento va specificato attraverso l'apposita proprietà  android:orientation. La peculiarità del LinearLayout è che tutti gli elementi vengono "impilati" uno di seguito all'altro, come dei blocchi. Non è possibile, quindi, far dipendere la posizione di una view da quella di un'altra; sono tuttavia disponibili diversi attributi con i quali ci si può divertire a giocare. Tra i più importanti è certamente da ricordare android:gravity, che ci permette di centrare o allineare gli elementi (a sinistra, a destra, al centro.

..): i valori sono anche mescolabili tra loro tramite il carattere |, come ad esempio "center|left".  Abbastanza utile può rivelarsi anche l'android:divider, che ci permette di caricare una nostra risorsa da utilizzare come divisore tra gli elementi.

Ma il più grande vantaggio del LinearLayout, nonché il motivo principale per cui viene usato, è certamente il weight: l'attributo relativo indica effettivamente quanto "peso" deve avere una componente grafica all'interno dell'interfaccia e va specificato non nella dichiarazione del Layout ma dei singoli elementi. Il tutto viene gestito molto bene da Android, che sarà in grado di scalare le dimensioni delle view a seconda della cifra che noi abbiamo stabilito all'interno di android:layout_weight.

Per fare un esempio, avendo due bottoni e dando ad entrambi il peso 1, questi si allargheranno fino a coprire l'intera grandezza della vista, che avrà come peso totale 2. Ognuno di essi occuperà quindi esattamente metà schermo. Se al primo dei due diamo un weight di 2, lasciando al secondo 1, noteremo che quest'ultimo occuperà 1/3 di schermata, sovrastato dall'altro che ne prenderà i 2/3.


In generale, Android assegnerà a tutta il layout un peso pari alla somma di tutti i figli, ma se vogliamo alterare quest'impostazione è possibile tramite l'attributo android:weightSum del LinearLayout.

Una volta imparati ad utilizzare, i pesi sono davvero comodi e, insieme ai margini (android:layout_margin) possono aiutarci a gestire  facilmente delle interfacce base. È possibile, come probabilmente saprete, inserire dei Layout all'interno di altri Layout: in questo caso, sebbene la tentazione sia tanta, è sconsigliato utilizzare il weight nel layout figlio: in questo caso si parla di nested weights (pesi annidati), che possono rallentare la creazione dell'interfaccia se devono eseguire calcoli complessi.

RelativeLayout

Discorso completamente diverso è con i RelativeLayout dove, come si può intuire dal nome, il posizionamento degli oggetti viene gestito in maniera relativa, vale a dire che ogni singolo elemento dipende dalla posizione di un altro. Per questo motivo la gran parte del lavoro la si fa gestendo gli attributi delle singole view e le proprietà che si possono impostare nel RelativeLayout in sé sono piuttosto poche.

Al contrario, possiamo impostare la posizione del primo (e, volendo anche degli altri) a partire dalla view che funge da contenitore, ovverosia da tutto il layout: per questo motivo possiamo utilizzare attributi come le seguenti:

  • alignParentTop
  • alignParentLeft
  • alignParentRight
  • alignParentBottom
  • centerVertical
  • centerHorizontal
  • ...

Il comportamento dei suddetti attributi è facilmente intuibile dal nome: ci consentono di allineare il nostro bottone (nel nostro caso), al layout padre, o di centrarlo; è inoltre possibile stabilire un margin, che andrà ad allontanare l'elemento dalla view  di riferimento. I margini sono impostati in dp che, come spiega la documentazione ufficiale, è un'unità di misura indipendente della densità. I dp devono essere il punto di partenza per supportare risoluzioni diverse e, con molta calma e aiutandosi anche con la conversione da dp a pixel, si riescono ad ottenere discreti risultati.

Una volta stabilita la posizione della prima view, dipendente dall'intera schermata, è possibile "ancorarne" altre: per esempio, è possibile inserire una TextView che varierà la sua posizione a seconda del bottone, e così via.

Per stabilire la posizione di un elemento dipendente da un altro, possiamo utilizzare attributi come:

  • above=idAltraView
  • below=idAltraView
  • toRightOf=idAltraView
  • toLeftOf=idAltraView

Questo ci consente, rispettivamente, di posizionare la nostra Textview sopra, sotto, a destra o a sinistra del tasto. È possibile, ovviamente, mescolare i vari attributi ed inserire dei margin: volendo inserire del testo sotto il bottone, quindi, potremo utilizzare una sintassi del genere:



    

    


Sebbene i RelativeLayout siano decisamente più flessibili dei Linear, purtroppo gli urli di disperazione sono dietro l'angolo nel caso vogliate modificare l'interfaccia o, peggio ancora, eliminare un elemento: considerando che ogni oggetto "dipende" da un altro, è caldamente consigliato un Clean del progetto ad ogni modifica sostanziale, in modo che vi vengano mostrate le effettiva nuove posizioni delle view.

Anche per questa settimana DevCorner vi saluta: speriamo di aver fornito quanto meno una panoramica generale sui due più comuni tipi di Layout e ci auguriamo che questa piccola spiegazione possa esservi d'aiuto nei momenti in cui vorrete lanciare il mouse dalla finestra.

Come sempre, se avete bisogno di aiuto (sì, anche per le interfacce!), potete porre le vostre domande nella sezione Sviluppo e programmazione del nostro forum.

Happy coding!

Via: DevCorner