Android tutorial: RecyclerView and CardView

Artem Fedin
111 minutes
Published in
5 min readApr 9, 2015

When the new Android OS was announced at the Google I/O conference 2014, everyone involved in the Android World was excited. Named for the lollipop, Android L rocked the audience with its new material design evincing a cleaner and more papery look. New possibilities for animation, components, and widgets also impressed.

The day after its introduction, developers received access to the updated Android SDK, which contained raw new classes of widgets just waiting to be discovered, explored, and implemented in apps prepared for Android L’s release. These new widgets were made available as part of the AppCompat v7 library, which allows the same UI to be replicated on Android API versions starting with API 7.

A lot of blog posts have been written about these new and interesting components by gurus from the world of Android, but we wanted to see for ourselves just how easy it is to use the new widgets and other components from lollipop. What follows is a series of tutorials on some of the cool new things from Android’s latest OS.

Since Android market trends suggest that some versions of the OS are quietly dying, we will write the project for Ice-Cream Sandwich version 4.0 (api 14).

This tutorial is dedicated to the two new widgets: RecyclerView and CardView.

Let’s start!

In our opinion, the most interesting widget featured in Lollipop and the AppCompat library version 21.0.0. is RecyclerView.

RecyclerView is incredibly interesting because it acts as a replacement to several oft relied-upon widgets like ListView and GridView. Because it is both more flexible and advanced than either of the aforementioned widgets, it’s also a bit more difficult to implement, requiring one of various Layout Managers to arrange elements. Currently, only a few of these managers are available right out of the box: LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager.

Another cool feature is the pattern ViewHolder, which helps improve the performance of ListView. Though not originally required, the pattern ViewHolder is now mandatory in custom adapters.

We will show a list of our favorite albums. First, create a layout for Activity, which will contain a RecycleView.

<RelativeLayout 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" tools:context=".MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycle_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"/>
</RelativeLayout>

It is as simple as adding ListView.

Since the API version of our application is lower than 21 (remember, we’re using Ice Cream Sandwich), we need to add this dependency in the build.gradle file :

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

Now in onCreate method we can reference and customize our RecycleView:

public class MainActivity extends ActionBarActivity { 
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
RecyclerView albumsRecycleView = (RecyclerView) findViewById(R.id.recycle_view); albumsRecycleView.setHasFixedSize(true);
GridLayoutManager recycleLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false); albumsRecycleView.setLayoutManager(recycleLayoutManager); albumsRecycleView.setItemAnimator(new DefaultItemAnimator()); RecycleCardsAdapter albumsAdapter = new RecycleCardsAdapter(DataUtils.getAlbumsData()); albumsRecycleView.setAdapter(albumsAdapter);
}

Here we specify the Layout Manager that will arrange item views in a row or, in our case, in two columns. You can specify the arrangement of the elements in two rows if you provide a horizontal orientation. If you want each item to occupy one row, you can use LinearLayoutManager, which like LinearLayout is capable of arranging elements horizontally and vertically.

Now let’s proceed to the look of items which our RecycleView will display. We will use CardView, a new UI component which displays information in the form of cards and allows us to customize its corners, elevation, and so on. We will use this component to display the covers and titles of our favorite albums. These cards will later be the cells of RecycleView, but for now let us define our card layout:

<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" 
app:cardElevation="5dp"
android:layout_margin="7dp">
<RelativeLayout
android:layout_width="wrap_content" android:layout_height="wrap_content">
<ImageView android:id="@+id/image_holder" android:layout_width="match_parent"
android:layout_height="155dp"
android:scaleType="fitXY" />
<View android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@id/image_holder" android:background="@android:color/darker_gray"/>
<TextView android:id="@+id/text_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@id/divider" android:layout_toLeftOf="@+id/image_overflow"
android:maxLines="2"
android:padding="10dp"
android:text="Empty for now"
android:textSize="16sp"/>
<ImageView android:id="@+id/image_overflow" android:layout_width="20dp"
android:layout_height="wrap_content" android:layout_alignBottom="@+id/text_title" android:layout_alignParentRight="true" android:layout_below="@id/divider"
android:layout_marginRight="7dp" android:src="@drawable/dots_vertical"/>
</RelativeLayout>
</android.support.v7.widget.CardView>

That’s how simple it is, though don’t forget to add the library containing CardView:

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

Now let’s create a model class Album, which is information on which we will display in an item view. Let’s also create a class that fills an array of objects with real data.

public class Album { 
private int mId;
private int mAlbumArt;
private String mTitle;
private String mArtistName;
private String mReleaseYear;
private String[] mSongTitles;
public Album(int id, int albumArt, String title, String artistName, String releaseYear, String[] songTitles) {
this.mId = id;
this.mAlbumArt = albumArt;
this.mTitle = title;
this.mArtistName = artistName;
this.mReleaseYear = releaseYear;
this.mSongTitles = songTitles;
}
}

Now that the basic elements of item view are specified and the model class is ready, we can go on to writing of the adapter for RecycleView. Custom adapters for RecyclerView should extend the class called RecyclerView.Adapter, to which our class that implements ViewHolder pattern should be passed.

The pattern class looks like this:

public static class CardViewHolder extends RecyclerView.ViewHolder{
ImageView mImageHolder;
TextView mTextTitle;
ImageView mImageOverflow;
public CardViewHolder(View itemView) {
super(itemView);
this.mImageHolder =(ImageView)itemView.findViewById(R.id.image_holder); this.mTextTitle = (TextView) itemView.findViewById(R.id.text_title);
this.mImageOverflow = (ImageView) itemView.findViewById(R.id.image_overflow);
}
}

To connect the data from our model with view elements, we need to use the onCreateViewHolder and onBindViewHolder methods. This first method is called when a new item view and class ViewHolder need to be inflated and created. The second method connects the data from the model with the view elements of ViewHolder that were created earlier.

public class RecycleCardsAdapter extends RecyclerView.Adapter<RecycleCardsAdapter.CardViewHolder> {
private ArrayList<Album> mAlbums;
public static class CardViewHolder extends RecyclerView.ViewHolder{
ImageView mImageHolder;
TextView mTextTitle;
ImageView mImageOverflow;
public CardViewHolder(View itemView) {
super(itemView);
this.mImageHolder = (ImageView) itemView.findViewById(R.id.image_holder);
this.mTextTitle = (TextView) itemView.findViewById(R.id.text_title);
this.mImageOverflow = (ImageView) itemView.findViewById(R.id.image_overflow);
}
}
public RecycleCardsAdapter(ArrayList<Album> albums) {
this.mAlbums = albums;
}
@Override
public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.card_layout, parent, false);
CardViewHolder cardViewHolder = new CardViewHolder(view);
return cardViewHolder;
}
@Override
public void onBindViewHolder(final CardViewHolder holder, final int listPosition) {
Album album = mAlbums.get(listPosition); holder.mImageHolder.setImageResource(album.getAlbumArt()); holder.mTextTitle.setText(album.getTitle());
}
@Override
public int getItemCount() {
return mAlbums.size();
}
}

Run the app and you’ll get the result shown below:

Written by: Yana Klimenko on April 9, 2015.

Originally published at 111 Minutes Blog.

--

--

Artem Fedin
111 minutes

Freelancer, Product Manager at Periodix, Coffee Lover