Android RecyclerView, exemple de tutoriel Android CardView

Android RecyclerView et Android CardView ont été introduits dans Android Lollipop avec Material Design. Pour ceux qui ne connaissent pas le Material Design, il s’agit d’un guide complet des widgets UI introduits depuis Android 5.0 et il améliore l’attrait visuel des applications.

Android RecyclerView

Android RecyclerView est une version plus avancée, puissante et flexible du ListView. Android RecyclerView est similaire au ListView sauf qu’il nous oblige à utiliser la classe RecyclerView.ViewHolder pour contenir les éléments, ce qui n’est pas une obligation dans ListView. Comme son nom l’indique, Android RecyclerView est utilisé pour réutiliser les cellules lors du défilement vers le haut et vers le bas en recyclant les éléments de la liste. Une autre amélioration de RecyclerView est qu’il nous permet de définir les LayoutManagers dynamiquement à l’exécution, contrairement au ListView qui était uniquement disponible dans une liste déroulante verticale. RecyclerView nous permet de définir les types de mises en page suivants à l’exécution.

  • LinearLayoutManager : prend en charge à la fois les listes verticales et horizontales
  • StaggeredLayoutManager : il prend en charge les listes décalées
  • GridLayoutManager : il prend en charge l’affichage des grilles telles qu’on les voit dans GalleryView plus tôt

Classes Android RecyclerView

  • La classe RecyclerView.ItemAnimator fournit un meilleur support pour l’animation des vues contrairement aux ListViews
  • La classe RecyclerView.ItemDecorator fournit un meilleur support lorsqu’il s’agit d’ajouter des bordures et des séparateurs, donnant ainsi un grand contrôle à l’utilisateur

Par conséquent, un RecyclerView est plus personnalisable par rapport à ListView et donne un plus grand contrôle aux utilisateurs. Le RecyclerView est disponible dans la bibliothèque de support. Nous devons donc modifier notre script gradle pour ajouter la dépendance suivante.

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

CardView Android

Le composant d’interface utilisateur CardView Android affiche des informations à l’intérieur de cartes. Ce composant est généralement utilisé pour afficher des informations de contact. Ce composant est disponible dans une autre bibliothèque de support, nous devons donc également ajouter sa dépendance.

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

Le widget CardView d’Android nous permet de contrôler la couleur de fond, l’ombre, le rayon des coins, l’élévation, etc. Pour utiliser les attributs personnalisés dans XML, nous devons ajouter la déclaration d’espace de noms suivante à la mise en page parente. Voici la déclaration d’espace de noms avec certains attributs de notre projet.

<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">

Les attributs importants utilisés ci-dessus sont :

  • card_view:cardCornerRadius : Utilisé pour définir le rayon des coins dans nos mises en page
  • card_view:cardBackgroundColor : Utilisé pour définir la couleur de fond de la vue

Dans notre projet d’exemple, nous ajouterons un RecyclerView pour afficher une liste de CardViews contenant des noms et des numéros de version d’Android ainsi qu’un logo d’exemple. Le onclick de CardView est programmé pour supprimer cette carte de la liste. Nous avons ajouté une option de menu dans l’ActionBar pour réintégrer les cartes supprimées dans l’ordre. Remarque : Les images de logo sont prises au hasard sur Google. Les tailles peuvent donc varier.

Exemple de RecyclerView et CardView d’Android

Le projet consiste en une MainActivity qui affiche le RecyclerView. Le CardView est ajouté au RecyclerView à partir de la classe CustomAdapter. Le DataModel est utilisé pour récupérer les données de chaque CardView via des getters. La classe MyData contient les tableaux de textviews et de drawables ainsi que leurs identifiants.

Exemple de code Android RecyclerView et CardView

Le fichier activity_main.xml contient le RecyclerView à l’intérieur d’un RelativeLayout comme indiqué ci-dessous. Code de 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>

La mise en page de la CardView Android est définie ci-dessous : code de 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>

La CardView Android contient une ImageView ainsi que deux TextViews dans un Layout linéaire imbriqué. Le fichier menu_main.xml contient un seul élément pour ajouter les cartes supprimées. Code de 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 est définie ci-dessous :

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) {
           // Vérifiez s'il y a des éléments à ajouter
            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);
    }
}

La méthode removeItems() est invoquée depuis la méthode auditrice pour supprimer la CardView cliquée. Son identifiant respectif est stocké dans un tableau pour le récupérer ultérieurement. Pour ajouter la vue plus tard, nous avons implémenté une autre méthode nommée addRemovedItemToList(). Dans cette méthode, nous ajoutons cette vue à une position prédéfinie dans la liste et supprimons son identifiant du tableau removedItems. Le CustomAdapter est notifié dans les deux cas. La classe CustomeAdapter.java est définie ci-dessous :

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();
    }
}

Dans le code ci-dessus, nous avons implémenté notre propre ViewHolder en étendant RecyclerView.ViewHolder. La vue est gonflée depuis le fichier cards_layout.xml que nous avions défini dans le répertoire des mises en page. Le onClickListener dans MainActivity est attaché à cette vue dans le snippet ci-dessous.

view.setOnClickListener(MainActivity.myOnClickListener);

Un ArrayList stocke toutes les données sous forme d’objet de classe DataModel dans un ArrayList et les ajoute aux cartes respectives dans la liste. Les classes DataModel.java et MyData.java qui contiennent les données spécifiques à cette application sont données ci-dessous :

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};
}

Voici la sortie produite par notre application exemple Android RecyclerView et CardView. Comme vous pouvez le voir, l’élément supprimé est toujours ajouté au troisième indice (quatrième position dans la liste). Cela marque la fin de ce tutoriel sur RecyclerView et CardView Android. Vous pouvez télécharger le Projet Exemple Android RecyclerView CardView depuis le lien ci-dessous.

Téléchargez le projet exemple Android RecyclerView CardView

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