Android RecyclerView and CardView in Material Design Tutorial

Android RecyclerView and CardView in Material Design Tutorial

In this tutorial we are going to learning how to create android RecyclerView and CardView in Material Design. Android RecyclerView and CardView are two UI widget introduce in android L.

Android RecyclerView is similar to a ListView but it is more complex and efficient when compare to the ListView. To learn more about the Android RecyclerView, I will suggest you read my post on Android RecyclerView with Material Design.

On the other hand, the CardView is a ViewGroup which uses a card like contain to wrap its information. The android CardView widget has rounded corner property and it can also be elevated. The CardView will serve as a row item in the RecyclerView. Feel free and read more about CardView on my post on Android CardView and Toolbar with Material Design

Android support library version 7 contains these UI widget so in other to use them in our project we are going to add their dependency libraries in our build.gradle file.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.android.support:cardview-v7:21.0.+'
    compile 'com.android.support:recyclerview-v7:21.0.+'
}

What we will create

We are going to create a list of country items. Each country will contain a photo representation of the country’ photo and name.

The CardView will contain two Views – ImageView and TextView. The ImageView will hold the country photo while the TextView will hold the country name.

The Adapter class will bind the dataset to the View controls inside the CradView ViewGroup. One advantage of using the RecyclerView is that it reuse View elements that is hide from view and this reduces the need to call the expensive findViewById()  method in the Activity class.

Before we start with the coding, it is important we have an idea of what we have set out to achieve. The image is as shown below.

Android RecyclerView

Before we start, the first thing I will do is to list the environment and tools I used in this android tutorial but feel free to use whatever environment or tools you are familiar with.

Windows 7

Android Studio

Sony Xperia ZL

Min SDK 14

Target SDK 19

To create a new android application project, following the steps as stipulated below.

Go to File menu

Click on New menu

Click on Android Application

Enter Project name: AndroidRecyclerViewCardView

Package: com.inducesmile.androidrecyclerviewcardview

Keep other default selections.

Continue to click on next button until Finish button is active, then click on Finish Button

Once you are done with creating your project, make sure you change the package name if you did not use the same package.

We will start with our main layout file. Since we are using the default Activity and layout file so the layout file is activity_main.xml. Open your project activity_main.xml and copy and paste the code snippet below.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:background="@color/color_primary"
        android:minHeight="?attr/actionBarSize" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp"
        tools:context=".MainActivity">

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

    </RelativeLayout>

</LinearLayout>

The ToolBar widget will be use to replace the ActionBar so we have added the ToolBar and a RelativeLayout which will hold the main RecyclerView.

You can refer to my tutorial on android Toolbar with Material Design to learn more about how to use the new android Toolbar widget to replace ActionBar in android application.

Since we make use of the ToolBar, we are going to let Theme to inherit from Theme.AppCompat.Light.NoActionBar. This will remove the ActionBar from our activity page. The styles.xml file is as shown

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/color_primary</item>
        <item name="colorPrimaryDark">@color/color_primary_dark</item>
        <item name="colorAccent">@color/accent_color</item>
    </style>
</resources>

We have overridden the android default colorPrimary, colorPrimaryDark and the accentColor so we are going to create a new colors.xml file in our project values folder. Copy and paste the code in your colors.xml file.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="color_primary">#2196F3</color>
    <color name="color_primary_dark">#1976D2</color>
    <color name="accent_color">#ffffff</color>
</resources>

Since we decided to use the ToolBar in our project, I have added a logo and couple of Action Views in the menu. The menu_main.xml file code is as shown

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">

    <item android:id="@+id/action_settings"
        android:title="@string/action_settings"
        android:orderInCategory="100"
        app:showAsAction="never" />

    <item android:id="@+id/action_refresh"
        android:title="@string/action_refresh"
        android:icon="@drawable/ic_action_refresh"
        android:orderInCategory="200"
        app:showAsAction="ifRoom" />

    <item android:id="@+id/action_new"
        android:title="@string/action_new"
        android:icon="@drawable/ic_action_new"
        android:orderInCategory="300"
        app:showAsAction="ifRoom" />
</menu>

The strings.xml file is also updated. This file holds reference to string resources we will use in the application’s other resource files.

<resources>
    <string name="app_name">RecyclerView and CardView</string>
    <string name="action_settings">Settings</string>
    <string name="action_refresh">Settings</string>
    <string name="action_new">Settings</string>
    <string name="logo_desc">App logo</string>
    <string name="country_name">Nigeria</string>
</resources>

We are going to create an Adapter and our adapter will inflate a layout which will holder a single row of item in the RecyclerView. The layout will contain two View widgets as stated above.

<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardUseCompatPadding="true"
card_view:cardCornerRadius="8dp"
android:layout_marginBottom="16dp">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/country_photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:contentDescription="@string/action_settings"
        android:layout_centerInParent="true"
        android:src="@drawable/newyork"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/country_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="36sp"
        android:text="@string/country_name"
        android:textColor="@color/accent_color"
        android:textStyle="bold"
        android:layout_centerInParent="true"/>

</RelativeLayout>

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

Now let us go further and create the RecyclerView Adapter class which will inherit from RecyclerView.Adapter and inflate the layout we have created above. The RecyclerView Adapter must implement two methods.

The onCreateViewHolder(ViewGroup parent, int viewType)  is use to return an instance of a ViewHolder class while onBindViewHolder(RecyclerViewHolders holder, int position)  is use to bind the dataset to the layout View widgets. The RecyclerView adapter code is as shown.

package inducesmile.com.androidrecyclerviewcardview;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> {

    private List<ItemObject> itemList;
    private Context context;

    public RecyclerViewAdapter(Context context, List<ItemObject> itemList) {
        this.itemList = itemList;
        this.context = context;
    }

    @Override
    public RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {

        View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_list, null);
        RecyclerViewHolders rcv = new RecyclerViewHolders(layoutView);
        return rcv;
    }

    @Override
    public void onBindViewHolder(RecyclerViewHolders holder, int position) {
        holder.countryName.setText(itemList.get(position).getName());
        holder.countryPhoto.setImageResource(itemList.get(position).getPhoto());
    }

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

The RecyclerView makes use of the ViewHolder pattern. The ViewHolder class contain all the row item View and it uses a reference to the layout object to get the corresponding handles for our UI View widgets.

package inducesmile.com.androidrecyclerviewcardview;

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


public class RecyclerViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener{

    public TextView countryName;
    public ImageView countryPhoto;

    public RecyclerViewHolders(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
        countryName = (TextView)itemView.findViewById(R.id.country_name);
        countryPhoto = (ImageView)itemView.findViewById(R.id.country_photo);
    }

    @Override
    public void onClick(View view) {
        Toast.makeText(view.getContext(), "Clicked Country Position = " + getPosition(), Toast.LENGTH_SHORT).show();
    }
}

The wrap the dataset for each item row of our RecyclerView, an entity class is created. An object of this class is stored in a List class which is passed as a parameter for the RecyclerView Adapter class.

package inducesmile.com.androidrecyclerviewcardview;

public class ItemObject {

    private String name;
    private int photo;

    public ItemObject(String name, int photo) {
        this.name = name;
        this.photo = photo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPhoto() {
        return photo;
    }

    public void setPhoto(int photo) {
        this.photo = photo;
    }
}

Finally we will open the MainActivity.java file. First we have to get a handle for our ToolBar. Thereafter, the object of the ToolBar is set as the ActionBar using the Activity class method setSupportActionBar(ToolBar toolBar);

An instance of the linear layout manager is created and set as the layout manager for the RecyclerView object.

The setAdapter() of the RecyclerView class use the object of the adapter as paramter.

package inducesmile.com.androidrecyclerviewcardview;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends ActionBarActivity {

    private LinearLayoutManager lLayout;

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

        Toolbar topToolBar = (Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(topToolBar);
        topToolBar.setLogo(R.drawable.logo);
        topToolBar.setLogoDescription(getResources().getString(R.string.logo_desc));

        List<ItemObject> rowListItem = getAllItemList();
        lLayout = new LinearLayoutManager(MainActivity.this);

        RecyclerView rView = (RecyclerView)findViewById(R.id.recycler_view);
        rView.setLayoutManager(lLayout);

        RecyclerViewAdapter rcAdapter = new RecyclerViewAdapter(MainActivity.this, rowListItem);
        rView.setAdapter(rcAdapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
        if(id == R.id.action_refresh){
            Toast.makeText(MainActivity.this, "Refresh App", Toast.LENGTH_LONG).show();
        }
        if(id == R.id.action_new){
            Toast.makeText(MainActivity.this, "Create Text", Toast.LENGTH_LONG).show();
        }

        return super.onOptionsItemSelected(item);
    }

    private List<ItemObject> getAllItemList(){

        List<ItemObject> allItems = new ArrayList<ItemObject>();
        allItems.add(new ItemObject("United States", R.drawable.newyork));
        allItems.add(new ItemObject("Canada", R.drawable.canada));
        allItems.add(new ItemObject("United Kingdom", R.drawable.uk));
        allItems.add(new ItemObject("Germany", R.drawable.germany));
        allItems.add(new ItemObject("Sweden", R.drawable.sweden));

        return allItems;
    }
}

The click event listener is add to the View Holder class which is attached to the row item layout.

Save the file and run your project. If everything works for you, the project will appear like this in your device.

Android RecyclerView and CardView

You can download the code for this tutorial below. If you are having hard time downloading the tutorials, kindly contact me.

Remember to subscribe with your email so that you will be among the first to receive our new post once it is published

OTHER INTERESTING POSTS:

2 Comments

  1. Henry

Add a Comment