Dopo aver visto nel precedente tutorial come usare la classe SharedPreferences per memorizzare valori primitivi, vediamo ora un esempio completo di interfaccia grafica propria, che ci permetterà di modificare varie opzioni. In questo post vedremo un semplice esempio di un’applicazione che mette a disposizione una Activity di preferenze in cui impostare alcune opzioni dell’interfaccia grafica.
Activity di impostazioni delle preferenze
Spesso molte applicazioni Android contengono un’Activity che permette di impostare delle opzioni relative al funzionamento dell’applicazione stessa. L’interfaccia di questa Activity è solitamente una lista di voci di menù con checkbox nel caso in cui l’opzione sia un boolean o con un pulsante per aprire un dialog. Anche le impostazioni di Android stesso sono realizzate in questo modo, per esempio l’Activity che permette di modificare le impostazioni del display è la seguente:
Vediamo come aggiungere un’Activity simile a questa nella nostra applicazione, i valori saranno memorizzati in automatico utilizzando un oggetto SharedPreferences. Per prima cosa creiamo un file preferences.xml all’interno del progetto nella directory res/xml. Il contenuto del file sarà il seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="@string/titolo_activity"> <CheckBoxPreference android:key="usa_titolo_custom" android:title="@string/usa_titolo_custom" android:summary="@string/summary_usa_titolo_custom" /> <EditTextPreference android:key="titolo" android:dependency="usa_titolo_custom" android:title="@string/titolo_da_usare" android:dialogTitle="@string/titolo_da_usare" android:defaultValue="@string/titolo_custom" /> </PreferenceCategory> <PreferenceCategory android:title="@string/colore_di_sfondo"> <ListPreference android:key="colore" android:summary="@string/summary_colore_di_sfondo" android:title="@string/colore_di_sfondo" android:entries="@array/colori" android:defaultValue="#000000" android:entryValues="@array/codici_colori" android:dialogTitle="@string/colore_di_sfondo" /> </PreferenceCategory> </PreferenceScreen> |
In questo file abbiamo definito tre preferenze, le prime due sono raggruppate in una categoria, la terza è in una categoria a parte. Le categorie permettono di dividere le varie preferenze in più sezioni ognuna con un titolo. Le preferenze possono essere di vari tipi, in questo esempio abbiamo usato:
- CheckBoxPreference: viene mostrato un checkbox nella riga
- EditTextPreference: permette di impostare una stringa nel dialog che compare cliccando sulla riga
- ListPreference: permette di scegliere un valore da un dialog contenente una lista di opzioni
Un altro tag utilizzabile è MultiSelectListPreference, il comportamento è simile a quello di ListPreference ma con la multi-selezione dalla lista mostrata nel diaog.
In tutti i tag possiamo specificare vari attributi, i principali sono:
- android:key: chiave da usare per memorizzare il valore
- android:title: titolo mostrato nella riga
- android:summary: sottotitolo (opzionale) mostrato nella riga
- android:defaultValue: valore di default da mostrare
- android:dependency: imposta la dipendenza da un’altra preferenza (solitamente una CheckBoxPreference) specificando un id. In pratica la preferenza contenente questo attributo è disabilitata nel caso in cui quella da cui dipende non è selezionata
Nel caso di opzioni con un dialog usando android:dialogTitle può essere impostato il titolo del dialog. Tutte le stringhe non sono cablate all’interno di questo file xml ma fanno riferimento a un file xml esterno (di solito chiamato strings.xml) grazie alla sintassi @string/nome_stringa. Usando un file esterno l’applicazione può essere internazionalizzata facilmente aggiungendo un file xml diverso per ogni nuova lingua.
Per quanto riguarda la terza opzione di tipo ListPreference sono specificati due array che contengono i valori e le stringhe da mostrare nel dialog, anche in questo caso facciamo riferimento a un file esterno usando la sintassi @array/nome_array. I due array sono definiti nel file arrays.xml contenuto nella directory res/values:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="codici_colori"> <item>#000000</item> <item>#FF0000</item> <item>#00FF00</item> </string-array> <string-array name="colori"> <item>@string/nero</item> <item>@string/rosso</item> <item>@string/verde</item> </string-array> </resources> |
Per mostrare le preferenze appena definite creiamo una nuova Activity che estende PreferenceActivity. Nel metodo onCreate richiamiamo il metodo addPreferencesFromResource passando il riferimento al file appena creato (usiamo come sempre la classe R che contiene i riferimenti a tutte le risorse):
1 2 3 4 5 6 7 8 9 | public class PreferencesFromXml extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } } |
Finalmente vediamo il risultato del nostro lavoro:
Cliccando sulla terza riga viene mostrato un dialog per scegliere il colore di sfondo (senza doversi preoccupare di creare il dialog o la ListView):
Summary dinamico in base al valore
Nell’esempio appena visto i valori della seconda e terza opzione non sono mostrati, è necessario cliccare sulla riga per vedere il valore nel dialog. Per evitare questo click aggiuntivo è possibile usare il summary della preferenza. Nel metodo onCreate della Activity impostiamo il summary in base al valore corrispondente:
1 2 3 4 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); Preference titoloPrefs = findPreference(TITOLO_PREF); String valore = prefs.getString(TITOLO_PREF, getString(R.string.titolo_custom)); titoloPrefs.setSummary(valore); |
Ovviamente questo metodo è invocato solo quando l’Activity è creata e quindi il summary non è aggiornato quando il valore cambia. Per aggiornarlo in automatico aggiungiamo un listener sull’evento onPreferenceChange usando il metodo setOnPreferenceChangeListener:
1 2 3 4 5 6 7 8 9 | titoloPrefs.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference prefs, Object value) { prefs.setSummary((CharSequence) value); return true; } }); |
Un listener simile a questo può essere usato anche per eseguire controlli sul valore inserito, infatti il valore di ritorno del metodo onPreferenceChange indica se la preferenza deve essere salvata. Nel caso in cui il valore inserito non sia corretto possiamo mostrare un messaggio e ritornare false impedendo il salvataggio.
Uso dei valori impostati
I valori modificati dall’Activity vista possono essere letti nel modo consueto utilizzando un oggetto SharedPreferences. In questo esempio modifichiamo il titolo e il colore di sfondo dell’Activity principale dell’applicazione in base ai valori salvati nelle preferenze:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @Override protected void onResume() { super.onResume(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); String colorePref = prefs.getString(PreferencesFromXml.COLORE_PREF, PreferencesFromXml.COLORE_DEFAULT); int coloreDiSfondo = Color.parseColor(colorePref); findViewById(R.id.main_layout).setBackgroundColor(coloreDiSfondo); String titolo; if (prefs.getBoolean(PreferencesFromXml.USA_TITOLO_CUSTOM_PREF, false)) { titolo = prefs.getString(PreferencesFromXml.TITOLO_PREF, getString(R.string.titolo_custom)); } else { titolo = getString(R.string.app_name); } setTitle(titolo); } |
Impostando il colore di sfondo a rosso e cambiando il titolo, quello che si ottiene è questo:
Come sempre sono disponibili per il download i sorgenti di questo esempio da importare dentro Eclipse.
Alla prossima.
Ciao ho appena letto il tutorial e mi funziona ma non riesco a mettere una drawable come sfondo ! e possibile se si avete qualche suggerimento ?
grazie mille per il tutorial…è semplice e mi è stato molto utile…ma adesso voglio salvare lo stato di un toggleButton…è possibile con questo metodo??se avete qualche suggerimento ve ne sarei molto grato!! :))
Ottimo tutorial. Avrei una domanda, ho due layout che interagiscono per mostrare un’unica schermata, in uno c’è una listview e nell’altro ci sono due textview. La domanda è questa: come faccio a far cambiare colore sia al background della listview che alle textview contemporaneamente (vorrei poter inserire nelle preferenze la possibilità di far cambiare lo sfondo in un colore e le scritte in un altro es: sfondo bianco e testo nero. avendo a disposizione un solo tasto come nel tutorial es: bianco + nero oppure nero + bianco)? Essendo in due layout diversi come ci riesco? Grazie mille.