Esempio di tutorial Android RecyclerView, Android CardView

Android RecyclerView e Android CardView sono stati introdotti in Android Lollipop con Material Design. Per coloro che non sono a conoscenza del Material Design, è una guida completa agli elementi dell’interfaccia utente introdotta dall’Android 5.0 e migliora l’aspetto visivo delle app.

Android RecyclerView

Android RecyclerView è una versione più avanzata, potente e flessibile della ListView. Android RecyclerView è simile alla ListView tranne che nel fatto che ci obbliga ad utilizzare la classe RecyclerView.ViewHolder per contenere gli elementi, cosa che non è obbligatoria nella ListView. Come suggerisce il nome, Android RecyclerView viene utilizzato per riutilizzare celle quando si scorre su e giù, riciclando gli elementi nella lista. Un’altra miglioria in RecyclerView è che ci consente di impostare i LayoutManagers dinamicamente durante l’esecuzione, a differenza della ListView che era disponibile solo in un elenco di scorrimento verticale. RecyclerView ci consente di impostare i seguenti tipi di layout durante l’esecuzione.

  • LinearLayoutManager: supporta sia liste verticali che orizzontali.
  • StaggeredLayoutManager : supporta liste scalate
  • GridLayoutManager : supporta la visualizzazione delle griglie come visto in GalleryView in precedenza

Classi Android RecyclerView

  • La classe RecyclerView.ItemAnimator fornisce un migliore supporto per l’animazione delle viste rispetto alle ListView
  • La classe RecyclerView.ItemDecorator fornisce un migliore supporto quando si tratta di aggiungere bordi e divisorie, dando così un grande controllo a noi

Quindi un RecyclerView è più personalizzabile rispetto a ListView e dà maggiore controllo agli utenti. Il RecyclerView è disponibile nella libreria di supporto. Quindi dobbiamo modificare il nostro script di gradle per aggiungere la seguente dipendenza.

dependencies {
       compile 'com.android.support:recyclerview-v7:21.0.0-rc1'
 }

CardView Android

Il componente UI CardView di Android mostra informazioni all’interno di carte. Questo componente è generalmente utilizzato per mostrare informazioni di contatto. Questo componente è disponibile in un’altra libreria di supporto quindi dobbiamo aggiungere anche la sua dipendenza.

dependencies {
        compile 'com.android.support:cardview-v7:21.0.0-rc1'
        compile 'com.android.support:recyclerview-v7:21.0.0-rc1'
 }

Il widget Android CardView ci permette di controllare il colore dello sfondo, l’ombra, il raggio dell’angolo, l’elevazione, ecc. Per utilizzare gli attributi personalizzati in XML, è necessario aggiungere la seguente dichiarazione di namespace al layout principale. Di seguito è riportata la dichiarazione del namespace con alcuni attributi dal nostro progetto.

<android.support.v7.widget.CardView
        android:id="@+id/card_view"
        xmlns:card_view="https://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        card_view:cardBackgroundColor="@color/grey_300"
        card_view:cardCornerRadius="10dp"
        card_view:cardElevation="5dp"
        card_view:cardUseCompatPadding="true">

Gli attributi importanti utilizzati sopra sono:

  • card_view:cardCornerRadius: Utilizzato per impostare il raggio dell’angolo nei nostri layout
  • card_view:cardBackgroundColor: Utilizzato per impostare il colore dello sfondo della vista

Nel nostro progetto di esempio, aggiungeremo un RecyclerView per visualizzare un elenco di CardViews che contiene i nomi e i numeri delle versioni di Android insieme a un logo di esempio. Il onclick del CardView è programmato per rimuovere quella carta dall’elenco. Abbiamo aggiunto un’opzione di menu nella ActionBar per aggiungere di nuovo le carte rimosse in ordine. Nota: le immagini del logo sono prese casualmente da Google. Quindi le dimensioni potrebbero variare.

Esempio di Android RecyclerView e CardView

Il progetto è composto da una MainActivity che visualizza il RecyclerView. Il CardView viene aggiunto al RecyclerView dalla classe CustomAdapter. La classe DataModel è utilizzata per recuperare i dati per ciascun CardView attraverso i getter. La classe MyData contiene gli array di textviews e drawables insieme ai loro id.

Esempio di codice per Android RecyclerView e CardView

Il file activity_main.xml contiene il RecyclerView all’interno di un RelativeLayout come mostrato di seguito. Codice di activity_main.xml:

<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:background="@color/grey_300"
    >

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

</RelativeLayout>

Il layout di Android CardView è definito di seguito: Codice di cards_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:tag="cards main container">

    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        xmlns:card_view="https://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        card_view:cardBackgroundColor="@color/color_white"
        card_view:cardCornerRadius="10dp"
        card_view:cardElevation="5dp"
        card_view:cardUseCompatPadding="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            >

            <ImageView
                android:id="@+id/imageView"
                android:tag="image_tag"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:layout_weight="1"
                android:src="@drawable/ic_launcher"/>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="12dp"
                android:layout_weight="2"
                android:orientation="vertical"
                >

                <TextView
                    android:id="@+id/textViewName"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="10dp"
                    android:text="Android Name"
                    android:textAppearance="?android:attr/textAppearanceLarge"/>

                <TextView
                    android:id="@+id/textViewVersion"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="10dp"

                    android:text="Android Version"
                    android:textAppearance="?android:attr/textAppearanceMedium"/>

            </LinearLayout>
        </LinearLayout>

    </android.support.v7.widget.CardView>

</LinearLayout>

Android CardView contiene un ImageView insieme a due TextView in un layout lineare nidificato. Il file menu_main.xml contiene un singolo elemento per ripristinare le schede rimosse. Codice di menu_main.xml:

<menu xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    tools:context=".MainActivity">
    <item android:id="@+id/add_item"
        android:title="Add"
        android:orderInCategory="100"
        app:showAsAction="always"/>
</menu>

La classe MainActivity.java è definita di seguito:

package com.journaldev.recyclerviewcardview;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private static RecyclerView.Adapter adapter;
    private RecyclerView.LayoutManager layoutManager;
    private static RecyclerView recyclerView;
    private static ArrayList data;
    static View.OnClickListener myOnClickListener;
    private static ArrayList removedItems;

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

        myOnClickListener = new MyOnClickListener(this);

        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        recyclerView.setHasFixedSize(true);

        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());

        data = new ArrayList();
        for (int i = 0; i < MyData.nameArray.length; i++) {
            data.add(new DataModel(
                    MyData.nameArray[i],
                    MyData.versionArray[i],
                    MyData.id_[i],
                    MyData.drawableArray[i]
            ));
        }

        removedItems = new ArrayList();

        adapter = new CustomAdapter(data);
        recyclerView.setAdapter(adapter);
    }


    private static class MyOnClickListener implements View.OnClickListener {

        private final Context context;

        private MyOnClickListener(Context context) {
            this.context = context;
        }

        @Override
        public void onClick(View v) {
            removeItem(v);
        }

        private void removeItem(View v) {
            int selectedItemPosition = recyclerView.getChildPosition(v);
            RecyclerView.ViewHolder viewHolder
                    = recyclerView.findViewHolderForPosition(selectedItemPosition);
            TextView textViewName
                    = (TextView) viewHolder.itemView.findViewById(R.id.textViewName);
            String selectedName = (String) textViewName.getText();
            int selectedItemId = -1;
            for (int i = 0; i < MyData.nameArray.length; i++) {
                if (selectedName.equals(MyData.nameArray[i])) {
                    selectedItemId = MyData.id_[i];
                }
            }
            removedItems.add(selectedItemId);
            data.remove(selectedItemPosition);
            adapter.notifyItemRemoved(selectedItemPosition);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);
        if (item.getItemId() == R.id.add_item) {
           //verifica se ci sono elementi da aggiungere
            if (removedItems.size() != 0) {
                addRemovedItemToList();
            } else {
                Toast.makeText(this, "Nothing to add", Toast.LENGTH_SHORT).show();
            }
        }
        return true;
    }

    private void addRemovedItemToList() {
        int addItemAtListPosition = 3;
        data.add(addItemAtListPosition, new DataModel(
                MyData.nameArray[removedItems.get(0)],
                MyData.versionArray[removedItems.get(0)],
                MyData.id_[removedItems.get(0)],
                MyData.drawableArray[removedItems.get(0)]
        ));
        adapter.notifyItemInserted(addItemAtListPosition);
        removedItems.remove(0);
    }
}

Il metodo removeItems() viene invocato dal metodo listener per rimuovere la CardView cliccata. Il suo rispettivo ID è memorizzato in un array per recuperarlo in seguito. Per aggiungere la vista in seguito, abbiamo implementato un altro metodo chiamato addRemovedItemToList(). In questo metodo, aggiungiamo quella vista in una posizione predefinita nella lista e rimuoviamo il suo ID dall’array removedItems. Il CustomAdapter viene notificato in entrambi i casi. La classe CustomeAdapter.java è definita di seguito:

package com.journaldev.recyclerviewcardview;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {

    private ArrayList<DataModel> dataSet;

    public static class MyViewHolder extends RecyclerView.ViewHolder {

        TextView textViewName;
        TextView textViewVersion;
        ImageView imageViewIcon;

        public MyViewHolder(View itemView) {
            super(itemView);
            this.textViewName = (TextView) itemView.findViewById(R.id.textViewName);
            this.textViewVersion = (TextView) itemView.findViewById(R.id.textViewVersion);
            this.imageViewIcon = (ImageView) itemView.findViewById(R.id.imageView);
        }
    }

    public CustomAdapter(ArrayList<DataModel> data) {
        this.dataSet = data;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent,
                                           int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.cards_layout, parent, false);

        view.setOnClickListener(MainActivity.myOnClickListener);

        MyViewHolder myViewHolder = new MyViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int listPosition) {

        TextView textViewName = holder.textViewName;
        TextView textViewVersion = holder.textViewVersion;
        ImageView imageView = holder.imageViewIcon;

        textViewName.setText(dataSet.get(listPosition).getName());
        textViewVersion.setText(dataSet.get(listPosition).getVersion());
        imageView.setImageResource(dataSet.get(listPosition).getImage());
    }

    @Override
    public int getItemCount() {
        return dataSet.size();
    }
}

Nel codice sopra, abbiamo implementato il nostro ViewHolder estendendo RecyclerView.ViewHolder. La vista viene gonfiata da cards_layout.xml che abbiamo definito nella directory dei layout. L’OnClickListener in MainActivity è collegato a questa vista nel frammento sottostante.

view.setOnClickListener(MainActivity.myOnClickListener);

Un ArrayList memorizza tutti i dati sotto forma di oggetto della classe DataModel in un ArrayList e li aggiunge alle rispettive carte nella lista. Le classi DataModel.java e MyData.java, che contengono i dati specifici di questa applicazione, sono fornite di seguito:

package com.journaldev.recyclerviewcardview;

public class DataModel {

    String name;
    String version;
    int id_;
    int image;

    public DataModel(String name, String version, int id_, int image) {
        this.name = name;
        this.version = version;
        this.id_ = id_;
        this.image=image;
    }

    public String getName() {
        return name;
    }

    public String getVersion() {
        return version;
    }

    public int getImage() {
        return image;
    }

    public int getId() {
        return id_;
    }
}
package com.journaldev.recyclerviewcardview;

public class MyData {

    static String[] nameArray = {"Cupcake", "Donut", "Eclair", "Froyo", "Gingerbread", "Honeycomb", "Ice Cream Sandwich","JellyBean", "Kitkat", "Lollipop", "Marshmallow"};
    static String[] versionArray = {"1.5", "1.6", "2.0-2.1", "2.2-2.2.3", "2.3-2.3.7", "3.0-3.2.6", "4.0-4.0.4", "4.1-4.3.1", "4.4-4.4.4", "5.0-5.1.1","6.0-6.0.1"};

    static Integer[] drawableArray = {R.drawable.cupcake, R.drawable.donut, R.drawable.eclair,
            R.drawable.froyo, R.drawable.gingerbread, R.drawable.honeycomb, R.drawable.ics,
            R.drawable.jellybean, R.drawable.kitkat, R.drawable.lollipop,R.drawable.marsh};

    static Integer[] id_ = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
}

Di seguito è riportato l’output prodotto dalla nostra applicazione di esempio Android RecyclerView e CardView. Come puoi vedere, l’elemento rimosso viene sempre aggiunto al terzo indice (quarta posizione nella lista). Con questo si conclude questo tutorial su Android RecyclerView e CardView. Puoi scaricare il Progetto di esempio Android RecyclerView CardView dal link sottostante.

Scarica l’esempio di progetto di Android RecyclerView CardView

Source:
https://www.digitalocean.com/community/tutorials/android-recyclerview-android-cardview-example-tutorial