Semplice esempio di griglia Android che utilizza RecyclerView con GridLayoutManager (come il vecchio GridView)


227

So che RecyclerViewha sostituito la funzionalità del vecchio ListViewe GridView. Sto cercando un esempio molto semplice che mostri una configurazione minima della griglia usando RecyclerView. Non sto cercando lunghe spiegazioni in stile tutorial, solo un esempio minimo. Immagino che la griglia più semplice che imita il vecchio GridView sarebbe costituita dalle seguenti funzionalità:

  • più celle per riga
  • vista singola in ogni cella
  • risponde agli eventi clic

Risposte:


556

Risposta breve

Per coloro che hanno già familiarità con la creazione RecyclerViewdi un elenco , la buona notizia è che creare una griglia è sostanzialmente lo stesso. Basta usare a GridLayoutManagerinvece di a LinearLayoutManagerquando si configura RecyclerView.

recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));

Se hai bisogno di più aiuto di quello, dai un'occhiata al seguente esempio.

Esempio completo

Di seguito è riportato un esempio minimo che sarà simile all'immagine seguente.

inserisci qui la descrizione dell'immagine

Inizia con un'attività vuota. Eseguirai le seguenti attività per aggiungere la RecyclerViewgriglia. Tutto quello che devi fare è copiare e incollare il codice in ogni sezione. Successivamente puoi personalizzarlo in base alle tue esigenze.

  • Aggiungi dipendenze per classificare
  • Aggiungi i file di layout xml per l'attività e per la cella della griglia
  • Crea l'adattatore RecyclerView
  • Inizializza RecyclerView nella tua attività

Aggiorna dipendenze Gradle

Assicurarsi che le seguenti dipendenze siano nel gradle.buildfile dell'app :

compile 'com.android.support:appcompat-v7:27.1.1'
compile 'com.android.support:recyclerview-v7:27.1.1'

È possibile aggiornare i numeri di versione a quelli più attuali .

Crea layout attività

Aggiungi il RecyclerViewal tuo layout xml.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvNumbers"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

Crea layout cella griglia

Ogni cella nella nostra RecyclerViewgriglia avrà solo una singola TextView. Crea un nuovo file di risorse di layout.

recyclerview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:padding="5dp"
    android:layout_width="50dp"
    android:layout_height="50dp">

        <TextView
            android:id="@+id/info_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:background="@color/colorAccent"/>

</LinearLayout>

Crea l'adattatore

È RecyclerViewnecessario un adattatore per popolare le viste in ogni cella con i tuoi dati. Crea un nuovo file java.

MyRecyclerViewAdapter.java

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

    private String[] mData;
    private LayoutInflater mInflater;
    private ItemClickListener mClickListener;

    // data is passed into the constructor
    MyRecyclerViewAdapter(Context context, String[] data) {
        this.mInflater = LayoutInflater.from(context);
        this.mData = data;
    }

    // inflates the cell layout from xml when needed
    @Override
    @NonNull 
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
        return new ViewHolder(view);
    }

    // binds the data to the TextView in each cell
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.myTextView.setText(mData[position]);
    }

    // total number of cells
    @Override
    public int getItemCount() {
        return mData.length;
    }


    // stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView myTextView;

        ViewHolder(View itemView) {
            super(itemView);
            myTextView = itemView.findViewById(R.id.info_text);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
        }
    }

    // convenience method for getting data at click position
    String getItem(int id) {
        return mData[id];
    }

    // allows clicks events to be caught
    void setClickListener(ItemClickListener itemClickListener) {
        this.mClickListener = itemClickListener;
    }

    // parent activity will implement this method to respond to click events
    public interface ItemClickListener {
        void onItemClick(View view, int position);
    }
}

Appunti

  • Sebbene non strettamente necessario, ho incluso la funzionalità per l'ascolto degli eventi clic sulle celle. Questo era disponibile nel vecchio GridViewed è un bisogno comune. Puoi rimuovere questo codice se non ti serve.

Inizializza RecyclerView in Activity

Aggiungi il seguente codice alla tua attività principale.

MainActivity.java

public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {

    MyRecyclerViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // data to populate the RecyclerView with
        String[] data = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"};

        // set up the RecyclerView
        RecyclerView recyclerView = findViewById(R.id.rvNumbers);
        int numberOfColumns = 6;
        recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
        adapter = new MyRecyclerViewAdapter(this, data);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onItemClick(View view, int position) {
        Log.i("TAG", "You clicked number " + adapter.getItem(position) + ", which is at cell position " + position);
    }
}

Appunti

  • Si noti che l'attività implementa ItemClickListenerciò che abbiamo definito nel nostro adattatore. Questo ci consente di gestire gli eventi di clic delle celle in onItemClick.

Finito

Questo è tutto. Dovresti essere in grado di eseguire il tuo progetto ora e ottenere qualcosa di simile all'immagine in alto.

Continua

Angoli arrotondati

Colonne a montaggio automatico

Ulteriore studio


2
@ MarianPaździoch, Sì, l'ho appena fatto come esempio minimo. Potrebbe sicuramente utilizzare alcuni lavori di abbellimento. Proverò ad aggiornare questa risposta qualche volta in futuro.
Suragch,

1
Ho effettuato l'accesso solo per indicare che persone come te hanno mantenuto in vita questo portale e scalciato. Sono rimasto bloccato per due giorni prima di vedere questa soluzione. grazie mille
VarunJoshi129

1
@androiddeveloper, Gli elementi della griglia vengono disposti da sinistra a destra, dall'alto verso il basso. Lo scorrimento è verticale quando ci sono più elementi di quanti possano adattarsi allo schermo.
Suragch,

13
Lettori futuri, lascia che ti risparmi un po 'di tempo, la cosa fondamentale èrecyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
daka,

1
@daka, buon punto. Ho modificato la mia risposta per includerla all'inizio.
Suragch,

7

Anche se mi piace e apprezzo la risposta di Suragch , vorrei lasciare una nota perché ho scoperto che codificare l' adattatore ( MyRecyclerViewAdapter) per definire ed esporre il metodo Listener onItemClicknon è il modo migliore per farlo, a causa del non utilizzo dell'incapsulamento di classe correttamente. Quindi il mio suggerimento è di lasciare che l' adapter gestisca esclusivamente le operazioni di ascolto (questo è il suo scopo!) E separare quelle dall'attività che utilizza l' adapter ( MainActivity). Quindi è così che imposterei la classe Adapter:

MyRecyclerViewAdapter.java

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

    private String[] mData = new String[0];
    private LayoutInflater mInflater;

    // Data is passed into the constructor
    public MyRecyclerViewAdapter(Context context, String[] data) {
        this.mInflater = LayoutInflater.from(context);
        this.mData = data;
    }

    // Inflates the cell layout from xml when needed
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    // Binds the data to the textview in each cell
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String animal = mData[position];
        holder.myTextView.setText(animal);
    }

    // Total number of cells
    @Override
    public int getItemCount() {
        return mData.length;
    }

    // Stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TextView myTextView;

        public ViewHolder(View itemView) {
            super(itemView);
            myTextView = (TextView) itemView.findViewById(R.id.info_text);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            onItemClick(view, getAdapterPosition());
        }
    }

    // Convenience method for getting data at click position
    public String getItem(int id) {
        return mData[id];
    }

    // Method that executes your code for the action received
    public void onItemClick(View view, int position) {
        Log.i("TAG", "You clicked number " + getItem(position).toString() + ", which is at cell position " + position);
    }
}

Si noti che il onItemClickmetodo ora definito MyRecyclerViewAdapterè quello in cui si desidera codificare le attività per l'evento / azione ricevuta.

C'è solo una piccola modifica da fare per completare questa trasformazione: l' Attività non ha più bisogno di essere implementata MyRecyclerViewAdapter.ItemClickListener, perché ora è completamente eseguita dall'adapter . Questa sarebbe quindi la modifica finale:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    MyRecyclerViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // data to populate the RecyclerView with
        String[] data = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"};

        // set up the RecyclerView
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rvNumbers);
        int numberOfColumns = 6;
        recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
        adapter = new MyRecyclerViewAdapter(this, data);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);
    }
}

3
Che cosa succede se l'attività deve ascoltare gli eventi clic? ad es. passaggio di dati al relatore, esecuzione di una logica basata sull'elemento selezionato, tracciamento, ecc.
Ahmad Fadli

Sono d'accordo che Adapter dovrebbe gestire gli eventi clic, poiché contiene gli elementi con i dati al suo interno. @AhmadFadli se è necessario eseguire alcune operazioni nell'host dell'adattatore (un frammento o attività), è necessario creare un'interfaccia di callback con i metodi necessari. Il tuo host implementa questa interfaccia. E poi passi un'istanza del tuo host nel costruttore di Adapter. Avendo l'istanza dell'host è possibile chiamare i suoi metodi quando è necessario dal proprio adattatore. E il tuo host riceviamo richiamate. Questo è spesso usato quando devi lavorare con ActionMode. Quando fai clic lungo per selezionare gli elementi e utilizzare i pulsanti della barra delle azioni.
Kirill Karmazin,

Non sono d'accordo e penso che gli eventi relativi ai clic debbano essere elaborati nell'hosting Activity. Perché solo di essa la click ascoltatore può conoscere i Activitypunti di vista e altri Fragments, Activitiesecc L'adattatore può inviare solo clic gli eventi a livello superiore. Dovrebbe avere l'interfaccia ItemClickListener con così tanti eventi, quanti sono gli eventi che l'adattatore può visualizzare. Questa soluzione è stata scritta anche prima: stackoverflow.com/a/40563598/2914140 .
CoolMind

4

Devi impostare il layoutmanager di recyclerview sulla modalità Gridlayout, per fare questo Basta cambiare il codice quando vuoi Impostare il tuo LayoutManager di RecyclerView:

Nota: sostituisci il conteggio delle colonne desiderato con ### HELP ###

   recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),###HELP###));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.