ListView per creare Liste di Dati in Android
In questo tutorial introdurremo uno dei concetti più importanti a livello di rappresentazione dei dati in Android, ossia come visualizzare una sequenza di dati con possibilità di scorrimento verticale.
Ti servono: 25 minuti
Nello sviluppo del layout di comuni pagine web, è operazione quotidiana inserire le classice liste non ordinate rappresentate dalla combinazione di tag <ul><li>. Si usano per creare menu orizzontali, menu verticali, o per strutture più complesse ad esempio sequenza di righe uguali, con all'interno anche immagini e altri elementi. Il tutto poi "plasmato" con i css per rappresentarli nella forma e colore che desideriamo.
Tutto questo è possibile realizzarlo anche nel mondo Android, con qualche difficoltà in più purtroppo, ma come sempre, niente di complesso da spaccarsi la testa.
In Android le liste vengono usate per rappresentare dei dati uno sotto l'altro, tipicamente righe, con la possibilità di effettuare il classico scrolling per posizionarsi in fondo e in cima. Applicazioni come Twitter, Facebook etc fanno largo uso di queste strutture di dati, per visualizzare l'elenco dei Tweet o degli aggiornamenti nel caso di Facebook.
Ogniqualvolta io debba visualizzare dei dati in righe identiche, una sotto l'altra, con dati ad esempio prelevati da un database, le liste sono la struttura ideale.
Spesso è poi possibile interagire (tocco) con gli elementi di ogni riga della lista, sia aggiornandone il contenuto con i classici pulsanti di aggiorna presenti in molti layout, sia rendendo i singoli elementi della lista sensibili al tocco in modo da accedere, ad esempio, al dettaglio di una notizia o di un prodotto.
Cosa imparerai?
- Capirai come si riconosce un oggetto lista all'interno di un layout
- Capirai come codificare, a livello di layout, ogni elemento riga della lista
- Capirai come "iniettare" in dinamico dei dati, all'interno di una lista, con gli Adapter
Partiamo allora dalle tecniche per inserire nel nostro layout l'elemento chiave che ci permetterà di rappresentare la lista di dati, ossia il nostro elemento che prende il nome di ListView.
Se usiamo il nostro ADT, facilmente lo possiamo trascinare dalla palette (si trova sotto Composite), insieme ad esempio ad un TextView, giusto per creare un layout con del testo di spiegazione in cima. Alla fine avremo un codice xml facilmente comprensibile, che chiamerò per esempio activiy_list.xml, del tipo:
Esempio: activity_list.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@string/colorepage1"> <TextView android:id="@+id/textList" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="16dp" android:text="@string/HeaderList" /> <ListView android:id="@+id/listView1" // id della nostra lista android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/textList" android:layout_centerHorizontal="true" android:layout_marginTop="15dp" /> </LinearLayout>
Nel codice puoi osservare la presenza del tag <ListView> che rappresenta proprio il nostro blocco, all'interno del quale andremo a inserire i diversi componenti riga della lista. Infatti, a differenza dell'html in cui gli elementi della lista sono tipicamente tag <li>, in Android è necessario specificare il tipo e il layout dei dati che vogliamo inserire all'interno di quel particolare oggetto <ListView>.
Dove sono le righe?
A questo punto la domanda che forse ti sei chiesto sarà: come faccio ad incastrare i valori prelevati da una ipotetica fonte esterna di dati (file XML, database, file JSON), all'interno della nostra lista? Come posso far sì che in corrispondenza all'immagine del prodotto, compaia la relativa immagine, al titolo il relativo titolo e così via, così come visto nel tutorial "Leggere dati XML con Android"?
E come vado a definire il layout di ogni singola riga, visto che l'oggetto ListView non presenta alcun elemento che faccia capire dove inserire queste informazioni.
Ebbene, è necessario introdurre un nuovo concetto importante, che vedremo potra' essere applicato ad altri elementi di un layout Android: il concetto di Adapter.
Cos'è un Adapter e a cosa serve?
Per gestire i dati da iniettare all'interno della lista, è necessario usare un oggetto intelligente il quale si prenda l'impegno di associare il dato corretto in relazione al layout definito per la riga del nostro componente ListView. Quindi se il dato che ho a disposizione è una stringa titolo, questo oggetto associerà alla posizione in cui ho definito il titolo nel layout della riga, il titolo stesso.
Analogo discorso per l'immagine e per la descrizione. L'oggetto intelligente in questione viene chiamato Adapter, in quanto funziona proprio come un adattatore tra due elementi: i dati e il layout/Activity.
Esistino numerose varianti di questi "adattatori" a seconda di qual è la natura dei dati che si vogliono mostrare (array o stringhe).
Uno dei più usati è l'ArrayAdapter, che, come dice lo stesso nome, permette di gestire dei dati memorizzati sotto forma di array.
Gli elementi su cui deve lavorare l'adapter sono essenzialmente 3:
- Deve conoscere il nome dell'arrayList che memorizza i dati da visualizzare riga per riga
- Devo conoscere dove recuperare il layout della singola riga
- Deve conoscere l'id dell'elemento ListView dove questi dati dovranno essere visualizzati nel layout
La prima domanda è di facile risposta, nell'ipotesi che io inserisca manualmente questi dati all'interno di un array di stringhe. Un array ricordo non è altro che una particolare variabile, che invece di memorizzare un solo valore, è in grado di memorizzarne diversi, e grazie all'uso di un indice numerico, io riesco ad individuarli ad uno ad uno nell'ordine in cui sono stati inseriti.
Pertanto i singoli valori dell'array di stringhe, potrebbero essere: Products1, Products2, Products3:
// definisco un array di stringhe String[] nameproducts = new String[] { "Product1", "Product2", "Product3" };
che potrei inserire all'interno di un arrayList, di nome listp, con un semplice ciclo for:
// definisco un array final ArrayList<String> listp = new ArrayList<String>(); for (int i = 0; i < nameproducts.length; ++i) { listp.add(nameproducts[i]); }
Nelle applicazioni reali vedremo, queste informazioni in realtà saranno recuperate direttamente da sorgenti esterne, quali db, file XML (vedi tutorial "Leggere dati da file XML in Android", lista contatti della rubrica o pagine web sotto forma di dati json (vedi corso jQuery).
Per rispondere alla seconda domanda, beh al solito, dovrò definire un file XML che rappresenti il layout della mia riga, facendo però attenzione che l'adattatore, nella forma predefinita permette di gestire solo un elemento di testo. Per layout di riga più complessi è necessario creare un adattatore personalizzato, come vedremo in altri tutorial. Questo il motivo per cui si usa un layot già predefinito in Android, che verrà richiamato con una sintassi molti simile al recuper di risorse, con la differenza di far precedere la R dalla parola android.
android.R.nomelayoutpredefinito 'recupero un layout predefinito in Android NON creato da me
Per rispondere alla terza domanda, anche qui noi sappiamo che esiste il metodo findViewById() che permette di recuperare un elemento del nostro layout sulla base di un attributo id. L'elemento che dobbiamo recuperare è l'oggetto ListView inserito in precedenza all'interno del layout di nome activity_list.xml
Pertanto ricordandoci il nome dell'identificativo, che è listView1, scriveremo:
final ListView mylist = (ListView) findViewById(R.id.listView1);
A questo punto, sara' sufficiente creare l'oggetto ArrayAdapter e dirgli dove si trovano i dati da inserire per ogni riga (listp) e dove si devono inserire (mylist):
final ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,android.R.layout.simple_list_item_1, listp); mylist.setAdapter(adapter);
Avrai notato che il secondo parametro del costruttore ArrayAdapter è un layout simple_list_item_1. Dove è stato definito? IN realtà non è stato definito da nessuna parte. E' un valore già presente all'interno di Android e rappresenta la singola riga di un classico ListView. Vedremo in seguito come personalizzare anche questo elemento al fine di visualizzare non solo una stringa, come è ora, ma anche altre informazioni come per esempio un'immagine e altro testo.
NB: Non dimenticarti di aggiungere nel file AndroidManifest.xml, il nome della nuova activity che conterrà tutto il codice scritto qui sotto:
Esempio: MyActivityList.java
public class MyActivityListView extends AppCompactActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list); // definisco un array di stringhe String[] nameproducts = new String[] { "Product1", "Product2", "Product3" }; // definisco un ArrayList final ArrayList <String> listp = new ArrayList<String>(); for (int i = 0; i < nameproducts.length; ++i) { listp.add(nameproducts[i]); } // recupero la lista dal layout final ListView mylist = (ListView) findViewById(R.id.listView1); // creo e istruisco l'adattatore final ArrayAdapter <String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listp); // inietto i dati mylist.setAdapter(adapter); } }
A questo punto siamo riusciti, con concetti in parte ancora da spiegare e chiarire, a creare una semplice lista di elementi che è possibile scorrere.
E' chiaro che questo sara' la base per poter poi implementare nuove funzionalità, come ad esempio la possibilità di personalizzare il layout della singola riga, aggiungendo ad esempio un'immagine oltre al singolo testo, oppure la possibilità di rendere cliccabile la singola riga dell'elemento ListView per aprire una nuova Activity, oppure per visualizzare un messaggio in popup etc etc, cosa che vedremo nel prossimo Tutorial, su "ListView gestire il tocco su una riga", in cui impareremo a gestire il click/tocco su ogni elemento della riga presente nel controllo ListView.
2024-12-13 Tipo/Autore: Davide Copelli {ing} Pubblicato da: CorsoAndroid.it