Crea elenchi dinamici con RecyclerView Parte di Android Jetpack.
RecyclerView semplifica la visualizzazione efficiente di grandi set di dati. Fornisci i dati e definisci l'aspetto di ogni elemento, mentre la libreria RecyclerView crea dinamicamente gli elementi quando sono necessari.
Come suggerisce il nome, RecyclerView ricicla questi singoli elementi. Quando un elemento scorre fuori dallo schermo, RecyclerView non distrugge la sua visualizzazione. Invece, RecyclerView riutilizza la visualizzazione per i nuovi elementi che sono stati visualizzati sullo schermo. RecyclerView migliora le prestazioni e la reattività della tua app, oltre a ridurre il consumo energetico.
Classi principali
Diverse classi collaborano per creare la tua lista dinamica.
RecyclerViewè ilViewGroupche contiene le visualizzazioni corrispondenti ai tuoi dati. È una visualizzazione, quindi aggiungiRecyclerViewal tuo layout come faresti con qualsiasi altro elemento UI.Ogni singolo elemento dell'elenco è definito da un oggetto view holder. Quando viene creato, il view holder non ha dati associati. Dopo la creazione del view holder,
RecyclerViewlo associa ai relativi dati. Puoi definire il view holder estendendoRecyclerView.ViewHolder.RecyclerViewrichiede le visualizzazioni e le associa ai relativi dati chiamando i metodi nell'adattatore. Definisci l'adattatore estendendoRecyclerView.Adapter.Il gestore del layout dispone i singoli elementi nell'elenco. Puoi utilizzare uno dei gestori di layout forniti dalla libreria RecyclerView o definirne uno tuo. I gestori del layout si basano tutti sulla classe astratta
LayoutManagerdella libreria.
Puoi vedere come tutti i componenti si integrano nell'app di esempio RecyclerView (Kotlin) o nell'app di esempio RecyclerView (Java).
Passaggi per l'implementazione di RecyclerView
Se vuoi utilizzare RecyclerView, devi eseguire alcune operazioni, che sono spiegate in dettaglio nelle sezioni seguenti.
Decidi l'aspetto dell'elenco o della griglia. In genere, puoi utilizzare uno dei gestori di layout standard della libreria RecyclerView.
Progetta l'aspetto e il comportamento di ogni elemento dell'elenco. In base a questo design, estendi la classe
ViewHolder. La tua versione diViewHolderfornisce tutte le funzionalità per gli elementi dell'elenco. Il tuo view holder è un wrapper attorno a unViewe questa visualizzazione è gestita daRecyclerView.Definisci il
Adapterche associa i tuoi dati alle visualizzazioniViewHolder.
Sono disponibili anche opzioni di personalizzazione avanzate che ti consentono di adattare RecyclerView alle tue esigenze specifiche.
Pianifica il layout
Gli elementi in RecyclerView sono disposti da una classe
LayoutManager. La libreria RecyclerView fornisce tre gestori di layout, che gestiscono le situazioni di layout più comuni:
LinearLayoutManagerdispone gli elementi in un elenco unidimensionale.GridLayoutManagerdispone gli elementi in una griglia bidimensionale:- Se la griglia è disposta verticalmente,
GridLayoutManagertenta di fare in modo che tutti gli elementi di ogni riga abbiano la stessa larghezza e altezza, ma righe diverse possono avere altezze diverse. - Se la griglia è disposta orizzontalmente,
GridLayoutManagertenta di fare in modo che tutti gli elementi di ogni colonna abbiano la stessa larghezza e altezza, ma colonne diverse possono avere larghezze diverse.
- Se la griglia è disposta verticalmente,
StaggeredGridLayoutManagerè simile aGridLayoutManager, ma non richiede che gli elementi di una riga abbiano la stessa altezza (per le griglie verticali) o che gli elementi della stessa colonna abbiano la stessa larghezza (per le griglie orizzontali). Di conseguenza, gli elementi di una riga o di una colonna possono risultare sfalsati tra loro.
Devi anche progettare il layout dei singoli elementi. Questo layout è necessario quando progetti il view holder, come descritto nella sezione successiva.
Implementa l'adattatore e il view holder
Una volta determinato il layout, devi implementare Adapter e
ViewHolder. Queste due classi interagiscono per definire la modalità di visualizzazione dei dati. ViewHolder è un wrapper attorno a un View che contiene il layout di un singolo elemento nell'elenco. Adapter crea oggetti ViewHolder in base alle esigenze e imposta anche i dati per queste visualizzazioni. Il processo di associazione delle visualizzazioni ai relativi dati è chiamato associazione.
Quando definisci l'adattatore, esegui l'override di tre metodi chiave:
onCreateViewHolder():RecyclerViewchiama questo metodo ogni volta che deve creare un nuovoViewHolder. Il metodo crea e inizializzaViewHoldere il relativoViewassociato, ma non compila i contenuti della visualizzazione:ViewHoldernon è ancora stato associato a dati specifici.onBindViewHolder():RecyclerViewchiama questo metodo per associare unViewHolderai dati. Il metodo recupera i dati appropriati e li utilizza per compilare il layout del view holder. Ad esempio, seRecyclerViewmostra un elenco di nomi, il metodo potrebbe trovare il nome appropriato nell'elenco e compilare il widgetTextViewdel view holder.getItemCount():RecyclerViewchiama questo metodo per ottenere le dimensioni del set di dati. Ad esempio, in un'app di rubrica, potrebbe essere il numero totale di indirizzi. RecyclerView utilizza questo valore per determinare quando non ci sono più elementi che possono essere visualizzati.
Ecco un esempio tipico di un semplice adattatore con un ViewHolder nidificato che
mostra un elenco di dati. In questo caso, RecyclerView mostra un semplice elenco di elementi di testo. All'adattatore viene passato un array di stringhe contenente il testo per gli elementi ViewHolder.
Kotlin
class CustomAdapter(private val dataSet: Array<String>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() { /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView init { // Define click listener for the ViewHolder's View textView = view.findViewById(R.id.textView) } } // Create new views (invoked by the layout manager) override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { // Create a new view, which defines the UI of the list item val view = LayoutInflater.from(viewGroup.context) .inflate(R.layout.text_row_item, viewGroup, false) return ViewHolder(view) } // Replace the contents of a view (invoked by the layout manager) override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.textView.text = dataSet[position] } // Return the size of your dataset (invoked by the layout manager) override fun getItemCount() = dataSet.size }
Java
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private String[] localDataSet; /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ public static class ViewHolder extends RecyclerView.ViewHolder { private final TextView textView; public ViewHolder(View view) { super(view); // Define click listener for the ViewHolder's View textView = (TextView) view.findViewById(R.id.textView); } public TextView getTextView() { return textView; } } /** * Initialize the dataset of the Adapter * * @param dataSet String[] containing the data to populate views to be used * by RecyclerView */ public CustomAdapter(String[] dataSet) { localDataSet = dataSet; } // Create new views (invoked by the layout manager) @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { // Create a new view, which defines the UI of the list item View view = LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.text_row_item, viewGroup, false); return new ViewHolder(view); } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder viewHolder, final int position) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.getTextView().setText(localDataSet[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return localDataSet.length; } }
Il layout di ogni elemento della visualizzazione è definito in un file di layout XML, come di consueto.
In questo caso, l'app ha un file text_row_item.xml simile al seguente:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:gravity="center_vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/element_text"/>
</FrameLayout>
Passaggi successivi
Il seguente snippet di codice mostra come utilizzare RecyclerView.
Kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val dataset = arrayOf("January", "February", "March") val customAdapter = CustomAdapter(dataset) val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = customAdapter } }
Java
RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.layoutManager = new LinearLayoutManager(this) recyclerView.setAdapter(customAdapter);
La libreria offre anche molti modi per personalizzare l'implementazione. Per saperne di più, consulta Personalizzazione avanzata di RecyclerView.
Attiva la visualizzazione edge-to-edge
Segui questi passaggi per attivare la visualizzazione edge-to-edge per un RecyclerView:
- Configura un display edge-to-edge compatibile con le versioni precedenti chiamando
enableEdgeToEdge(). - Se gli elementi dell'elenco si sovrappongono inizialmente alle barre di sistema, applica gli inserti su
RecyclerView. Puoi farlo impostandoandroid:fitsSystemWindowssutrueo utilizzandoViewCompat.setOnApplyWindowInsetsListener. - Consenti il disegno delle voci dell'elenco sotto le barre di sistema durante lo scorrimento impostando
android:clipToPaddingsufalseinRecyclerView.
Il seguente video mostra un RecyclerView con la visualizzazione edge-to-edge disattivata
(a sinistra) e attivata (a destra):
Esempio di codice di inserimento:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener( findViewById(R.id.my_recycler_view) ) { v, insets -> val innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "or WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ) v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom) insets }
Java
ViewCompat.setOnApplyWindowInsetsListener( activity.findViewById(R.id.my_recycler_view), (v, insets) -> { Insets innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "| WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ); v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom ); return insets; } );
Il file XML RecyclerView:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Risorse aggiuntive
Per saperne di più sui test su Android, consulta le seguenti risorse.