Corso Programmazione Android Lezione 3: Le risorse
Le altre lezioni del Corso di Programmazione Android sono reperibili a questo indirizzo
Dopo le prime due lezioni prettamente introduttive è ore di studiare una parte importante per la programmazione Android: le risorse.
Teoria
Questa settimana ho deciso per una teoria corta (anche perché la pratica è prettamente teorica) quindi vediamo un’immagine che può aiutarci a riconoscere i componenti grafici principali di un’applicazione Android (accostata alla nostra Activity). L’immagine è utilizzata nella documentazione ufficiale per spiegare quali sono le costanti usate per colorare le varie componenti.
Partiamo dall’alto: il componente al quale è associato colorPrimaryDark lo conosciamo tutti è la barra delle notifiche, il componente subito sotto è l’actionBar (colorPrimary) che in Material Design rappresenta la Toolbar, come detto la scorsa lezione il pulsante rotondo è un Floating Action Button, mentre in basso abbiamo la navigation bar. Come si evince possiamo cambiare il colore a ogni componente, persino alla barra di navigazione di Android.
Pratica
Quando si parla di programmazione Android, per risorse intendiamo tutti i file che “vivono” nella cartella res del nostro progetto, quindi file contenenti:
- Colori
- Definizione layout (Activity e altro)
- Definizione voci di menu
- Definizione di stringhe (nelle varie lingue)
- Array di stringhe (praticamente raggruppamenti di stringhe)
- Immagini varie (drawable o mipmap che siano)
- Temi dell’applicazione
Colori
Ebbene si partiamo dai più semplici (anche perché quel blu mi da abbastanza sui nervi). Come è facile intuire il file che ci interessa è colors.xml (in res/values). Al momento contiene:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> </resources>
Da questo file, oltre a definire colori personalizzati, possiamo cambiare i colori della Toolbar (colorPrimary) , della NavigationBar (colorPrimaryDark) e del FAB (colorAccent). Per ora i colori sono letti solo all’interno dello stile.
Sul sito developer.android.com troviamo (fra le tante guide) anche una palette molto completa, consultabile qui. Per i colori viene utilizzata la classica RBG
Mi piace abbastanza il verde quindi trasformiamo la nostra app:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#00796B</color> <color name="colorPrimaryDark">#004d40</color> <color name="colorAccent">#00796B</color> </resources>
Meglio no?
Layout
Analizziamo adesso il layout della nostra Activity, così da poter, a cascata, analizzare quasi tutte le altre risorse.
Nella lezione precedente abbiamo detto che è il nostro layout è specificato in due file layout/activity_main.xml e layout/content_main. Questa divisione serve solo ad aumentare le leggibilità del codice (o al riuso, ma non è questo il caso).
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.begeekmyfriend.bereader.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>
Come si può vedere componenti con dei figli si chiudono con </NomeComponente> mentre quelli che non hanno figli si chiudono con />. Potremmo utilizzare il primo formato per tutti i componenti , ma la notazione corta è più leggibile.
Abbiamo il contenitore principale CoordinatorLayout, e tre componenti figli: AppBarLayout (che a sua volta ha Toolbar come figlio), include (che incolla un file separato) e FloatingActionButton. Vediamo il CoordinatorLayout:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.begeekmyfriend.bereader.MainActivity"> . . . . </android.support.design.widget.CoordinatorLayout>
Per prima cosa vengono richiamati i componenti principali di ogni file xml che si rispetti, gli schemas. Gli schemas sono quelli che un normale xml hanno estensione xsd cioè la composizione del file (il componente x può assumere solo valore y e z che deve essere numerico, ecc).
Dopo di che vengono definite le dimensioni in larghezza (layout_width) e in altezza (layout_height), entrambi i parametri possono contenere i seguenti valori (validi per tutti i componenti):
- match_parent: imposta tutta lo spazio che serve per riempire il genitore (in questo caso non essendoci un genitore si occupa tutta la schermata)
- fill_parent: deprecato, ma in alcuni esempi in rete si trova, è sostituito da match_parent
- wrap_content: imposta la sola dimensione necessaria a contenere l’oggetto
- dimensione in px pixel
- dimensione in dp
Utilizzando i dp (diversi dai dpi) usiamo un’unita di misura che mantiene una coerenza anche con risoluzioni diverse. E’ un’unita di misura convenzionale.
Occupiamoci adesso dell’AppBar:
<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout>
Stiamo definendo un contenitore (figlio di CoordinatorLayout) AppBarLayout che prende tutto lo spazio in larghezza e tutto lo spazio necessario in altezza (quindi prenderà le dimensioni richieste da suo figlio) e che utilizzerà lo stile AppBarOverlay.
Al suo interno abbiamo la Toolbar vera e propria. Le associamo prima di tutto un id (usiamo @+id per crearne uno nuovo), così da poterci interagire via codice o via altri componenti, dopo di che ordiniamo di utilizzare tutto lo spazio messo a disposizione dal suo contenitore in larghezza e la costante di sistema ?attr/actionBarSize in altezza.
Il file separato lo vedremo fra poco, completiamo quindi il file con il componente FloatingActionButton:
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" />
Anche qui associamo un id, definiamo le dimensioni (il necessario sia in larghezza che in altezza) e aggiungiamo altri parametri, vediamoli uno alla volta:
- layout_gravity: definisce la posizione fissa del componente , applichiamo due valori (separati da | ) botton (in basso) e end (alla fine del contenitore)
- layout_margin: definisce i margini, quindi la distanza dagli altri componenti. Non abbiamo specificato se sopra (_top), sotto (_bottom), sinistra (_left) o destra (_right) quindi applica i margini globalmente. Come valore richiamiamo un dimen (nel file /values/dimens)
- src: associamo un’icona di sistema (@android:) ma potremmo associarne una personalizzata usando @mipmap/nomefile (senza estensione)
content_main.xml
Vediamo adesso il file content_main.xml (che abbiamo visto essere incluso con <include layout=”@layout/content_main” />):
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.begeekmyfriend.bereader.MainActivity" tools:showIn="@layout/activity_main"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </RelativeLayout>
Abbiamo il contenitore padre RelativeLayout (figlio anch’esso di CoordinatorLayout), dobbiamo definire nuovamente gli schemas trovandoci su un nuovo file.
Riempiamo il contenitore con il nostro layout e definiamo i padding (distacco dal bordo del genitore, infatti possiamo vedere che c’è uno spazio actionbar scritta e bordo estremo-scritta), per farlo usiamo un dimen. Stavolta definiamo il padding lato per lato (anche se come vedremo più avanti la costante ha sempre lo stesso valore).
Al suo interno inseriamo una TextView (semplice casella di testo):
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" />
Anche qui definiamo le dimensioni (usiamo solo lo spazio necessario) e al suo interno inseriamo una stringa.
Altre risorse
Vediamo i file delle risorse dimen e string
Dimen
Il file dimens.xml, contenuto nella cartella res/values, ha questo formato:
<resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> <dimen name="fab_margin">16dp</dimen> </resources>
Come per i color abbiamo un “marcatore padre” resources (comune a molte risorse) e dei componenti dimen all’interno.
<dimen name="activity_horizontal_margin">16dp</dimen>
Dove definiamo il nome (utilizzato poi per richiamare la risorsa) e il valore in dp. Qundi tutti i componenti che abbiamo visto sono distanti fra loro 16dp (per prova potete aumentare i dp e vedere come cambia l’anteprima sulla destra)
String
Le stringhe hanno formato simile:
<resources> <string name="app_name">BeReader</string> <string name="action_settings">Settings</string> </resources>
Qui definiamo due stringhe: il nome della nostra App e il contenuto del menù.
Mi fa strano notare che Android Stuudio all’interno del file content_main abbia piazzato direttamente la stringa, ma ancora di più che da codice abbia fatto lo stesso per il click sul pulsante FAB.
fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view,"Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } });
Per adesso abbiamo finito, nella prossima lezione inizieremo a modificare il codice Java del nostro progetto e vedremo gli stili.
Originariamente pubblicato su Be Geek My Friend