Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 22 di 97
  • livello avanzato
Indice lezioni

ListView e GridView

Visualizzare gli elementi in liste o in una griglia.
Visualizzare gli elementi in liste o in una griglia.
Link copiato negli appunti

Tra le tante View di cui dispone Android, ne esiste una categoria particolarmente importante. Costituisce buona parte delle interfacce di cui sono dotate le app che usiamo. Stiamo parlando delle AdapterView e del loro rapporto con gli Adapter.

Adapter e AdapterView

Finora abbiamo apprezzato due modalità diverse per realizzare le varie parti delle nostre app:

  • design in XML, per layout e risorse, dall'approccio piuttosto visuale ma orientato alla definizione di parti statiche;
  • sviluppo in Java, fondamentale per le funzionalità dinamiche ma meno pratico per il disegno di porzioni di layout.

Ma se dovessimo realizzare una "via di mezzo": una visualizzazione iterativa di contenuti archiviati in strutture dati, potenzialmente variabili, come dovremmo comportarci? In fin dei conti, è un caso comunissimo, pensiamo alle app che mostrano liste di messaggi di vario genere, elenchi di notizie o risultati di una query su database.

Tutti questi lavori vengono affrontati con Adapter e AdapterView dove:

  • Adapter è un componente collegato ad una struttura dati di oggetti Java (array, Collections, risultati di query) e che incapsula il meccanismo di trasformazione di questi oggetti in altrettante View da mostrare su layout;
  • AdapterView è un componente visuale che è collegato ad un adapter e raccoglie tutte le View prodotte dall'adapter per mostrarle secondo le sue politiche.

Passiamo subito ad un esempio pratico.

ListView, un AdapterView molto comune

Il primo esempio su questo argomento fondamentale viene fatto usando la più comune degli AdapterView, la ListView, ed il più immediato degli Adapter, l'ArrayAdapter.

Il problema è: abbiamo un array di oggetti String e vorremmo che, iterativamente, una View ci mostrasse tutte le stringhe disposte in righe.

Agiamo così:

  • otteniamo un riferimento alla struttura dati, in questo caso l'array di String;
  • istanziamo un ArrayAdapter assegnandogli, via costruttore, l'array che fungerà da sorgente dei dati e il layout da usare per ogni singola riga;
  • recuperiamo la ListView predisposta nel layout e le assegniamo il riferimento all'adapter che sarà il suo “fornitore” di View.

Creiamo due layout:

  • uno per l'Activity, nel file activity_main.xml, costituito solo dalla ListView:
    <ListView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
  • l'altro per la singola riga, in row.xml, contenente solo la TextView che mostrerà il testo di ogni riga:
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="28sp"
        android:padding="8dp"/>

Il collegamento dinamico tra struttura dati/Adapter/Listview viene realizzato nell'onCreate dell'activity:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    String[] citta= {"Torino","Roma","Milano","Napoli","Firenze"};
    ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, R.layout.row,citta);
    ListView listView = findViewById(R.id.listview);
    listView.setAdapter(adapter);
}

L'immagine seguente mostra il risultato:

L'ArrayAdapter è il caso più semplice di Adapter ma è comunque di uso molto frequente. Nella documentazione ufficiale è possibile trovare molti altri adapter già inclusi nel framework facilmente integrabili nelle proprie applicazioni.

GridView

Dire che la ListView nell'esempio precedente ha fatto molto poco non è del tutto sbagliato. La logica che trasforma gli oggetti in View è totalmente incluso nell'adapter. La ListView, o in generale gli AdapterView, si limitano in molti casi a recuperare View dall'adapter e a mostrarle nel layout.

Se volessimo sostituire la ListView con un altro AdapterView, diciamo la GridView specializzata in griglie, dovremmo compiere molto lavoro? Decisamente no.

Sarà sufficiente:

  • nel layout, sostituire la ListView con la GridView, assegnando un numero di colonne alla griglia:
    <GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gridview"
    android:numColumns="3"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
  • nel codice Java semplicemente sostituire l'uso della classe ListView con GridView:
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String[] citta= {"Torino","Roma","Milano","Napoli","Firenze"};
        // sostituiamo ListView con GridView
        ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, R.layout.row,citta);
        GridView gridView = findViewById(R.id.gridview);
        gridView.setAdapter(adapter);
    }

La figura mostra come le View non saranno più mostrate in lista ma in una griglia a tre colonne.

Gestione degli eventi

Gli AdapterView hanno un altro ruolo molto importante: la gestione degli eventi. Come per tutte le View viene effettuato mediante il meccanismo dei listener. Un caso molto comune è la gestione del click su un elemento della lista, ciò che viene normalmente interpretato come selezione.

Tornando all'esempio della GridView, se volessimo far visualizzare un Toast che notifica quale elemento è stato selezionato dovremmo inserire il seguente codice:

GridView gridView = findViewById(R.id.gridview);
gridView.setOnItemClickListener(
   (AdapterView<?> av, View v, int pos, long id) ->
    {
        Toast.makeText(getApplicationContext(),
                "Selezionato "+citta[pos], Toast.LENGTH_LONG).show();
    }
);

Abbiamo utilizzato un'espressione lambda per fornire il codice che gestirà l'evento di click. I parametri in input conterranno tutte le informazioni utili tra cui:

  • l'elemento su cui si è cliccato (il secondo, di classe View);
  • la posizione che ricopre nella struttura (il terzo parametro, di tipo int). All'interno del metodo onItemClick si vede come l'informazione della posizione è stata sfruttata per recuperare dalla struttura dati l'oggetto (citta[pos]).

Proseguire lo studio di AdapterView e Adapter

Quello che è iniziato con questo capitolo è un argomento importante e molto articolato. Rappresenta un blocco fondamentale della UI Android.

Lo studio dell'argomento dovrà proseguire innanzitutto scoprendo i vari tipi di AdapterView disponibili nel framework. Nel prosieguo della guida ne verranno presentati altri tra cui, a brevissimo, lo Spinner ma per il resto la documentazione ufficiale rimarrà una fonte inestimabile di informazioni.

Altrettanto importante sarà apprezzare le potenzialità degli Adapter. In particolare, sarà fondamentale imparare a realizzare un Adapter Custom in cui andremo a definire una logica personalizzata di trasformazione degli oggetti in View.

Più si andrà avanti con lo studio degli Adapter, più si dovrà considerare che la quantità di dati affidata a questi componenti è spesso rilevante, rendendoli soggetti ad abusi di risorse, potenzialmente letali per l'applicazione. La documentazione ufficiale ha proposto accorgimenti da adottare per evitare tutto ciò, ma ci si è reso conto che una forma di AdapterView già ottimizzato solleverebbe il programmatore dalla responsabilità di attuare in proprio meccanismi di sicurezza: per questo è nata la RecyclerView, che abbiamo approfondito su questo sito e che potrà costituire un'ottima alternativa agli AdapterView tradizionali.

Ti consigliamo anche