Giu 162011
 

Dopo aver visto brevemente com’è formato un progetto Android e cosa sono le view,  in questa terza puntata andiamo a scoprire le basi dell’interfaccia grafica di un’applicazione Android cominciando dai layout. Ma cos’è un layout? Questo è uno dei termini che manterrò in lingua inglese ma, se volessimo tradurlo, potremmo usare parole quali schema, impaginazione, disposizione. In parole semplici non è altro che una rappresentazione della disposizione degli elementi grafici sullo schermoorienttion. Qualcuno potrebbe obbiettare che per disegnare ad esempio un pulsante rettangolare, ci possano bastare le coordinate x ed y di uno spigolo, larghezza ed altezza. Ciò sarebbe vero se la nostra applicazione dovesse funzionare su un’unico tipo di dispositivo con una risoluzione grafica fissa, immutevole nel tempo. Ma Android funziona su dispositivi con risoluzioni grafiche diverse ed il nostro obiettivo è creare un’interfaccia che si adegui alle variazioni dello schermo in modo automatico permettendo a tutti di usufruire della nostra applicazione. Per questo motivo molte interfacce grafiche moderne permettono la descrizione dell’interfaccia in modo che questa possa variare dinamicamente in base all’hardware su cui va a girare, anche se possiamo sempre decidere di non seguire questo principio. Veidamo una carellata dei layout disponibili:

  1. LAbsoluteLayout, diciamolo subito, pur ancora presente, è segnalato come “deprecato” da Google stessa, il che significa che ne viene sconsigliato l’utilizzo e molto probabilmente prima o poi verrà rimosso dal sistema operativo rendendo le applicazioni scritte con questo layout incompatibili con future versioni. Il motivo per cui è stato accantonato è proprio quello prima detto, infatti con questo layout gli elementi vengono posti sullo schermo fornendo coordinate tramite pixel, il che crea un’interfaccia statica, non adattabile al variare della grandezza del display. Nei nostri articoli non verrà nemmeno preso in considerazione.
  2. Il LinearLayout permette di distribuire gli elementi da visualizzare in righe e colonne in base agli attributi che gli forniamo. Ad esempio potremmo decidere di dividere lo schermo in due righe, quindi in un’area superiore ed una inferiore, e poi magari suddividere a sua volta l’area superiore in due colonne. All’interno degli spazi creati possiamo poi metterci cosa ci interessa. In questo modo andiamo a creare un’applicazione con un’interfaccia dinamica che si può espandere o contrarre in base alle dimensioni dello schermo.
  3. RelativeLayout è un layout molto potente che permette di posizionare gli elementi in maniera relativa o all’area del layout stesso specificando allineamenti del tipo “a sinistra, in basso” o in relazione ad elementi già visualizzati sullo schermo. Quindi l’elemento A potrebbe essere posto a destra rispetto B, poi potremmo mettere C in basso rispetto B, etc. Faccio notare che “gli elementi” di cui parlo, sono le view di cui abbiamo parlato nella precedente puntata.
  4. Il TableLayout permette di suddividere lo schermo in una tabella, quindi in righe e colonne, in modo analogo a quanto avviene con il comando table in html.
  5. GridView: suddivide lo schermo in una griglia 2D scrollabile. E’ molto utile ad esempio quando si devono fornire miniature di immagini da selezionare.
  6. TabLayout: è la classica suddivisione in tab, al giorno d’oggi pressochè onnipresente in qualunque software. Necessita di due elementi TabHost e TabWidget, ma ne riparleremo con degli esempi pratici.
  7. ListView: premette di posizionare sullo schermo una lista scrollabile di elementi, ad esempio l’elenco di nomi di persone fra cui selezionarne una.
  8. Il FrameLayout occupa un’area di schermo selezionabile e sovrapponibile ad altri layout pre-esistenti. E’ utile quando dobbiamo far comparire dei popup, ad esempio per avvisare l’utente di certi eventi.

LinearLayout

layout lineare android

Linear Layout

Ora però vediamo degli esempi concreti. Come primo esercizio ci proponiamo di preparare un layout come quello della figura qui accanto che altro non è che quello della guida ufficiale di Google a cui ho fatto una piccola modifica. Esso si basa sull’utilizzo del linearlayout per cui vediamo come procedere, passo a passo.  Quando vogliamo applicare questo tipo di layout possiamo procedere in questo modo. Definiamo innanzitutto una delle aree dello schermo a disposizione beninteso che  all’inizio di questo procedimento l’area corrisponderà a tutto lo schermo. In base alla suddivisione che vogliamo ottenere dobbiamo chiederci: come posso dividere in due quest’area in senso orrizontale o verticale per ottenere la suddivisione voluta? Nel nostro esempio possiamo fare una prima suddivisione in verticale tracciando una linea orrizondale che  suddivide l’area dello schermo in due sottoaree, una superiore dove per intenderci ci sono le 4 bande colorate, ed una inferiore in cui c’è la parte grigia e nera.

linearlayout primo step

Primo step

Qui vicino trovate la prima suddivisione in una parte alta, di colore rosso, ed una bassa di colore nero. Qui sotto invece troviamo il listato xml che dobbiamo usare per sostituire quello presente in main.xml per ottenere questo risultato. Ora andiamolo ad analizzarlo con più attenzione.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView android:text="rosso"  android:background="#aa0000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
<TextView android:text="riga 1" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
</LinearLayout>

Tralasciando la prima linea di intestazione xml, troviamo subito dopo il tag “LinearLayout” che si chiude in fondo al listato. Fra le opzioni troviamo android:orientation=”vertical”: questa è di fondamentale importanza in quanto indica la nostra intenzione di dividere l’area dello schermo in senso verticale. Le altre due opzioni sono layout_width e layout_height che rappresentano rispettivamente la larghezza e l’altezza del layout da disporre. La divisione che vogliamo effettuare interessa l’intero schermo per cui il nostro layout dovrà coprire l’intera area dello schermo per cui assegnamo sia all’altezza che alla larghezza il valore “fill_parent”, che significa “riempi l’area in cui sei stato messo”. (mi scuso per la traduzione molto personalizzata, ma credo che tradurre con “riempi genitore” sarebbe stato meno chiaro). Dentro il layout vengono annidati due “TextView” che come abbiamo visto nelle precedenti puntate servono ad inserire del testo sullo schermo. Nel nostro caso sono stati inseriti solamente per attribuirgli un colore di fondo e renderli visibili in quanto se impostassimo il colore di background del layout avremmo tutta la schermata del medesimo colore visto il layout copre tutta l’area anche se virtualmente diviso in mezzo, motivo per cui non potrebbe esserci una divisione fra le due porzioni con colori diversi. Il primo TextView utilizza text=rosso” per cui porrà la scritta “rosso” sullo schermo. Con gravity=”center_horizontal” indichiamo in che parte dell’area disponibile dovrà essere inserita la scritta, nel caso specifico sarà centrata lungo il senso orrizontale. Ci sono la bellezza di 23 diverse possibilità per descrivere la gravity, se morite dalla curiosità di conoscerle tutte subito potete andare alla guida ufficiale a questa pagina. Con background=#aa0000 impostiamo il colore di fondo del TextView che sarà di colore rosso.

Piccolo ripasso sulla notazione esadecimale.

Benchè la gran parte di chi sta leggendo conoscerà la notazione esadecimale utilizzata anche nella descizione dei colori e ampiamente usata in ogni linguaggio di programmazione, faccio un breve approfondimento per chi non conoscesse questo tipo di descrizione. Come potete vedere ci sono 6 cifre alfanumeriche che in realtà sono divise in tre gruppi da due. Quindi nel caso specifico ci saranno aa – 00 – 00. Ricordiamo che i numeri esadecimali vanno da 0 a F, il che significa che dopo il 9 c’è la a, la b, c, d, e,  f dove chiaramente la a varrà 10, la b varrà 11 fino alla f che varrà 16 (da cui il nome esadecimale). Dopo la f viene il 10 esadecimale che in decimale corrisponde al 17. Con due cifre esadecimali possiamo rappresentare valori che vanno da 00 a ff che tradotto in decimale corrisponde a 255 motivo per cui, comprendendo lo zero, possiamo rappresentare 256 valori diversi. Ogni gruppo di cifre corrisponde ad uno dei colori fondamentali, molti conosceranno la sigla, RGB, che significa Red-Green-Blue che in italiano diventa rosso, verde, blu, ossia l’esatta sequenza in cui sono rappresentati i tre valori di cui sopra. Ponendo tutti i valori a zero otteniamo il nero. Ponendoli tutti a FF otteniamo il bianco. Mettendo tutte le coppie di valori sullo stesso valore (ex #bbbbbb o #555555), otteniamo un colore particolare che prende il nome di “grigio”. Essendoci 256 valori per ogni colore fondamentale di conseguenza ci sono 256 toni di grigio due dei quali prendono il nome di nero e bianco. Fatta questa brevissima parentesi sui colori, il nostro sfondo sarà rosso in quanto ha una componente rossa (aa) e nessuna componente verde e blu (oo). Se al posto di aa mettessimo un valore maggiore avremmo un colore rosso più chiaro mentre con un valore inferiore uscirebbe un rosso più scuro.

Layout_height, layout_width e layout_weight

Layout_height e layout_width rappresentano rispettivamente i valori di altezza e larghezza del textview. Possiamo inserire dei valori statici in pixel del tipo 50px, 80px, 133px o ciò che vogliamo, cosa da fare però con attenzione visto che l’utilizzo di un’altezza o larghezza fissa ne impedisce il riadattamento in base alle dimensioni dello schermo, o, nel caso l’applicazione possa funzionare in una “finestra”, nel caso di ridimensionamento della finestra stessa. Ci sono però due valori particolari intravvisti prima che sono “fill_parent” e “wrap_content”. Il primo dice di riempire tutta l’altezza o la larghezza disponibile dell’area messa atextview wrap disposizione da chi contiene il textview, in questo caso il layout genitore. Nel nostro esempio abbiamo utilizzato “fill_parent” nella larghezza dei textview, in questo modo viene occupata tutta la larghezza del layout, e quindi dello schermo, anche se la scritta contenuta è molto più corta. Con “wrap_content” si istruisce android ad occupare lo spazio strettamente necessario a contenere il testo contenuto per cui avremmo avuto dei textview larghi esattamente quanto la rispettiva scritta contenuta, come visibile nell’immagine qui vicino (ho usato uno sfondo grigio altrimenti non si sarebbero visti i confini del textview nero). Un po’ più complesso da capire, è perchè abbiamo utilizzato wrap_content anche per l’altezza. Secondo quanto detto aremmo dovuto aver dei textview alti quanto la scritta contenuta e non a mezzo schermo ciascuno. Ma facciamo attenzione. Se avessimo usato fill_parent nel primo textview, quello rosso, questo avrebbe coperto tutta l’area dello schermo e non ci sarebbe più stato spazio per quello nero che, effettivamente, non verrebbe disegnato sullo schermo. Siamo perciò obbligati ad usare wrap_content, ma ci serve qualcosa che indichi ad android di occupare l’area disponibile lasciata vuota. Proprio per quasto c’è l’opzione layout_weight che deve essere impostata ad un valore diverso da zero. Ora proseguiamo per raggiungere l’obiettivo iniziale.

Il secondo step

All’inizio dicevamo di cercare aree divisibili in due per arrivare a costruire il layout che ci interessa. Questo tipo di tecnica in realtà me lo sono del tutto inventato per cercare di far avvicinare i più digiuni in materia a quella forma mentale che poi ci permetta di andare aventi con le nostre gambe. Guardando l’area nera in basso, possiamo individuare una possibile suddivisione in due per ottenere un’area nera a sinistra e grigia a destra. La domanda da porci ora è “in che punto inseriamo il nuovo layout ?”. In questo momento ci troviamo in una situazione di questo tipo:

<LinearLayout 1
  <TextView rosso ...
  <TextView nero ....
</LinearLayout>

In realtà è abbastanza semplice. Il textview nero già presente deve stare DENTRO il nuovo layout, ed insieme ad esso dovrà essere aggiunto il nuovo textview grigio per cui la soluzione che vogliamo ottenere sarà:

<LinearLayout 1
  <TextView rosso ...
  <LinearLayout 2
    <TextView nero ....
    <TextView grigio....
  </LinearLayout 2>
</LinearLayout 1>

Dato che il Layout2 va in un certo senso a sostituire quello che era il Textview nero, dovrà ereditare le stesse proprietà per quanto riguarda il riempimento di altezza e larghezza oltre che il layout_weight. Per quanto riguarda il paramentro “orintation”, questo sarà opposto al layout1 e corrisponderà a horizontal il che permette appunto di disporre il suo contenuto in senso orizzontale. Ora deve ssere fatta una piccola modifica al TextView nero in quanto prima occupava tutta la larghezza (fill_parent) mentre ora dovrà condividere lo pazio con il nuovo textview per cui modifichiamo la larghezza con wrap_content. Ora basta inserire il nuovo textview (grigio) che sarà quasi identico a quello nero se non per la scritta e colore di fondo.

android linearlayout

step2

Il listato finale sarà:

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
 <TextView android:text="rosso"  android:gravity="center_horizontal" android:background="#aa0000" android:layout_width="fill_parent" android:layout_weight="1" android:layout_height="wrap_content"/>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1">
  <TextView android:text="riga 1" android:textSize="15pt" android:background="#000000" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1"/>
  <TextView android:text="grigio" android:background="#444444" android:layout_height="fill_parent" android:layout_width="wrap_content" android:textSize="15pt" android:layout_weight="1"/>
 </LinearLayout>
</LinearLayout>

ed il risultato potete vederlo nell’immagine accanto.

Il terzo step ed i passi successivi

Ora dobbiamo procedere, a questo punto è indifferente se aggiungere le righe nello spazio nero o le bande colorate in quello rosso. Decido arbitrariamente di cominciare con lo spazio nero. Purtroppo non possiamo aggiungere semplicemente un TextView, in quanto il layout non farebbe altro che aggiungerlo al nero e grigio con la medesima disposizione. Noi dobiamo invece inserire al posto dello spazio nero, un layout che ci permette di disporre le nostre righe una sopra l’altra, quindi con un attributo orientation=”vertical”. Il nuovo layout andrà ad includere il textview nero, al quale saranno poi aggiunti i nuovi textview per raggiungere l’obiettivo prefissato all’inizio. Altra piccola modifica è la larghezza dei textview che essendo ora contenuti da uno specifico layout dovrenno avere l’attributo fill_parent invece che wrap_content. Il risultato sarà questo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#007700" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> 
 <TextView android:text="rosso"  android:gravity="center_horizontal" android:background="#aa0000" android:layout_width="fill_parent" android:layout_weight="1" android:layout_height="wrap_content"/>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#000077" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"> 
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#000077" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1">
    <TextView android:text="riga 1" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
    <TextView android:text="riga 2" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
    <TextView android:text="riga 3" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
    <TextView android:text="riga 4" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
  </LinearLayout>
  <TextView android:text="grigio" android:background="#444444" android:layout_height="fill_parent" android:layout_width="wrap_content" android:textSize="15pt" android:layout_weight="1"/>
 </LinearLayout>
</LinearLayout>

e l’immagine corrispondent sarà quella qui a fianco.

Step 3

Per concludere dobbiamo inserire le bande colorate che altro non sono che ulteriori textview con fondo di colori diversi. Come appena visto sostituiamo il textview rosso con un layout che ne ricalcherà la caratteristiche, poi spostiamo il textview rosso dentro il layout ricordandoci di modificare l’altezza per riempirlo completamente. In ultimo inseriamo nuovi textview a cui modifichiamo il colore di fondo e la scritta. Fatto questo l’opera è completa ed otteniamo il seguente listato:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#007700" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#000077" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1">
  <TextView android:text="rosso"  android:gravity="center_horizontal" android:background="#aa0000" android:layout_width="wrap_content" android:layout_weight="1" android:layout_height="fill_parent"/>
  <TextView android:text="verde"  android:gravity="center_horizontal" android:background="#00aa00" android:layout_width="wrap_content" android:layout_weight="1" android:layout_height="fill_parent"/>
  <TextView android:text="blu"  android:gravity="center_horizontal" android:background="#0000aa" android:layout_width="wrap_content" android:layout_weight="1" android:layout_height="fill_parent"/>
  <TextView android:text="giallo"  android:gravity="center_horizontal" android:background="#aaaa00" android:layout_width="wrap_content" android:layout_weight="1" android:layout_height="fill_parent"/>
 </LinearLayout>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#000077" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1">
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#000077" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1">
   <TextView android:text="riga 1" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
   <TextView android:text="riga 2" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
   <TextView android:text="riga 3" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
   <TextView android:text="riga 4" android:textSize="15pt" android:background="#000000" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"/>
  </LinearLayout>
  <TextView android:text="grigio" android:background="#444444" android:layout_height="fill_parent" android:layout_width="wrap_content" android:textSize="15pt" android:layout_weight="1"/>
 </LinearLayout>
</LinearLayout>

Step 4

L’immagine corrispondente è quella qui a fianco.

Possiamo notare che rispetto alla figura iniziale la suddivisione fra “parte alta” e “parte bassa” non è al 50% ma vi è un più dinamico addattamento delle scritte sullo sfondo nero. Se vogliamo ottenere l’effetto iniziale non dobbiamo far altro che impostare i due layout che includono le due porzioni con valori di altezza a fill_parent anzichè wrap_content, in questo modo si spartiranno lo spazio in maniera eguale. Lascio a voi questa semplice variazione come piccolo esercizio, comunque le linee da modificare sono la 3 e la 9. Spero che questo articolo così dettagliato non sia stato troppo pesante, ma credo possa essere molto utile a chi non ha dimestichezza con le interfacce grafiche e si avvicina per la prima volta a questi argomenti. Spero vivamente ci siano dei commenti anche perchè se non ho un feedback mi è difficile capire se gli articoli che scrivo, spendendo molto tempo, sono chiari o meno, se vi sono utili o non servono a nulla. Nella o nelle  prossime puntate andremo a dare uno sguardo anche ai restanti layout.

  One Response to “Sviluppare applicazioni android: parte 3 – Layout”

  1.  

    Grazie! Pensavo che il problema maggiore era java+android, invece anche la UI non è così facile da apprendere 🙂

    Pol