One of the latest widgets introduced in Android is RecyclerView. Many say its a replacement of existing ListView widget, also termed as ListView 2.0. I browsed though the entire world wide web, in search of a working Android RecyclerView example with explanation. Gotta say couldn’t find one. After a lot of struggle I finally made one and decided to write a tutorial for it my self. So here it goes, in this Android RecyclerView Tutorial I would demonstrate a working example of RecyclerView, with some basic functionality. Where I would show you how to include a RecyclerView into an Android app project with an onItemClick event.
Android RecyclerView falls under the material design of android. Hence to maintain backward compatibility, first I would suggest you to go through my article on maintaining backward compatibility of material design. I will try to keep this tutorial on Android RecyclerView short and simple as it consists a huge number of classes and each one of them is designed to be customized.
Android RecyclerView: A basic Introduction
Just like ListView, RecyclerView is used to display a large amount of similar items on screen. But since the Android team was building an enhancement, they added a bunch of new features to RecyclerView. Each one of these new features, give a platform to developers for implementing a highly custom made RecyclerView. One of the custom implementations of RecyclerView is the new Gmail app on Android. I took inspiration from it and tried to make a subset of it, in this Android RecyclerView Tutorial. Below I will discuss the 4 key classes of RecyclerView but first lets add its dependency in build.gradle(:app):-
dependencies { implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:recyclerview-v7:27.1.1' }
RecyclerView with different layouts
One of the new concepts introduced in RecyclerView is the Layout managers. This class basically defines the type of layout which RecyclerView should use. In RecyclerView you can define three types of LayoutManager (s).
LinearLayoutManager
– This LayoutManager can be used to display linear lists, they could be vertical or horizontal.GridLayoutManager
– Earlier in android GridView was the only widget to display grids, but now with RecyclerView, GridLayoutManager can be used to display grids.StaggeredGridLayoutManager
– Another great customization is StaggeredGridLayoutManager, this is used to display a staggered grid.
In this Android RecyclerView Tutorial for simplicity I will be using a LinearLayoutManager for displaying a vertical list of items.
Android RecyclerView ViewHolder
The concept of RecyclerView.ViewHolder is same as it was in the ListView. Simply said: when a view goes out of visible area it is kept for recycling. Earlier this was done through the custom view holder pattern. But now with RecyclerView a ViewHolder class is included in the adapter by default. Therefore now its a compulsion for everyone to implement this class. There are many advantages to this approach, like it keeps references to the views in your items, which in turn decreases the overhead of creating new references every time an item is displayed.
Have a look at the object, that I will be using to supply data to ViewHolder:
package com.truiton.recyclerviewexample; public class DataObject { private String mText1; private String mText2; DataObject (String text1, String text2){ mText1 = text1; mText2 = text2; } public String getmText1() { return mText1; } public void setmText1(String mText1) { this.mText1 = mText1; } public String getmText2() { return mText2; } public void setmText2(String mText2) { this.mText2 = mText2; } }
Also have please have look at the layout where RecyclerView needs to be added:
<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=".RecyclerViewActivity"> <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>
Android RecyclerView Adapter
In general ListView implementations, the adapters were used to bind views with positions, usually in the getView()
method. As developers we used to bind data into it. Here in RecyclerView the concept is same. But now the difference is, that new view holders are placed inside the adapter and the adapter now binds with ViewHolder, instead of views, as in previous adapters. In a way a direct binding between ViewHolder and position is made. To understand the concept mode deeply have a look at my custom implementation of RecyclerView.Adapter
:
package com.truiton.recyclerviewexample; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.ArrayList; public class MyRecyclerViewAdapter extends RecyclerView .Adapter<MyRecyclerViewAdapter .DataObjectHolder> { private static String LOG_TAG = "MyRecyclerViewAdapter"; private ArrayList<DataObject> mDataset; private static MyClickListener myClickListener; public static class DataObjectHolder extends RecyclerView.ViewHolder implements View .OnClickListener { TextView label; TextView dateTime; public DataObjectHolder(View itemView) { super(itemView); label = (TextView) itemView.findViewById(R.id.textView); dateTime = (TextView) itemView.findViewById(R.id.textView2); Log.i(LOG_TAG, "Adding Listener"); itemView.setOnClickListener(this); } @Override public void onClick(View v) { myClickListener.onItemClick(getAdapterPosition(), v); } } public void setOnItemClickListener(MyClickListener myClickListener) { this.myClickListener = myClickListener; } public MyRecyclerViewAdapter(ArrayList<DataObject> myDataset) { mDataset = myDataset; } @Override public DataObjectHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.recyclerview_item, parent, false); DataObjectHolder dataObjectHolder = new DataObjectHolder(view); return dataObjectHolder; } @Override public void onBindViewHolder(DataObjectHolder holder, int position) { holder.label.setText(mDataset.get(position).getmText1()); holder.dateTime.setText(mDataset.get(position).getmText2()); } public void addItem(DataObject dataObj, int index) { mDataset.add(dataObj); notifyItemInserted(index); } public void deleteItem(int index) { mDataset.remove(index); notifyItemRemoved(index); } @Override public int getItemCount() { return mDataset.size(); } public interface MyClickListener { public void onItemClick(int position, View v); } }
Android RecyclerView onItemClick Event
Sadly the standard implementation of RecyclerView does not have an onItemClick implementation. Instead they support touch events by adding an OnItemTouchListener
through the addOnItemTouchListener
method of RecyclerView
class.
But I believe the suggested implementation is a little lengthy to implement. Also you may need to detect click events on the views in a RecyclerView item. Which may be a little difficult to implement through the standard OnItemTouchListener.
Therefore I have implemented a custom recyclerview onitemclick event.
Here in the above code sample, I defined a custom interface MyClickListener
with a method onItemClick
, which is used for detecting clicks on the activity. The only drawback of this approach is, that I had to make a static reference to MyClickListener
, inside the adapter. Although it may not create any problems, but still to avoid them I suggest you to initialize this interface in onResume()
method of your activity.
The above code implementation will detect clicks on the item. If you need to detect clicks on particular views. It can be done simply by modifying the code in DataObjectHolder
constructor. The layout for RecyclerView item:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/selectableItemBackground" android:orientation="vertical"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingTop="5dp" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge"/> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="5dp" android:paddingLeft="@dimen/activity_horizontal_margin" android:text="Small Text" android:textAppearance="?android:attr/textAppearanceSmall"/> </LinearLayout>
To display visual responses like ripples on screen when a click event is detected add selectableItemBackground
resource in the layout (highlighted above). Next have a look at the main activity where all of this code would come into play:
package com.truiton.recyclerviewexample; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import java.util.ArrayList; public class RecyclerViewActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private RecyclerView.Adapter mAdapter; private RecyclerView.LayoutManager mLayoutManager; private static String LOG_TAG = "RecyclerViewActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler_view); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); mRecyclerView.setHasFixedSize(true); mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); mAdapter = new MyRecyclerViewAdapter(getDataSet()); mRecyclerView.setAdapter(mAdapter); RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, LinearLayoutManager.VERTICAL); mRecyclerView.addItemDecoration(itemDecoration); // Code to Add an item with default animation //((MyRecyclerViewAdapter) mAdapter).addItem(obj, index); // Code to remove an item with default animation //((MyAdapter) mAdapter).deleteItem(index); } @Override protected void onResume() { super.onResume(); ((MyRecyclerViewAdapter) mAdapter).setOnItemClickListener( new MyRecyclerViewAdapter.MyClickListener() { @Override public void onItemClick(int position, View v) { Log.i(LOG_TAG, " Clicked on Item " + position); } }); } private ArrayList<DataObject> getDataSet() { ArrayList results = new ArrayList<DataObject>(); for (int index = 0; index < 20; index++) { DataObject obj = new DataObject("Some Primary Text " + index, "Secondary " + index); results.add(index, obj); } return results; } }
In the above code sample I have defined a basic Android RecyclerView. Where I have also shown, how to add and remove items at run time from the adapter. The good part here is, you need not to worry about animation. They are added and removed with default animation. But the most annoying thing is how to add dividers and spaces between items in RecyclerView?
Android RecyclerView Spacing Between Items
One of the biggest problems you might face while implementing Android RecyclerView is the spacing between items. Yes its true RecyclerView by default does not give any support for displaying dividers between items. Although you can add dividers by using an object of RecyclerView.ItemDecoration
class in mRecyclerView.addItemDecoration(itemDecoration)
method. Earlier this item decoration had to be implemented by the user itself but now it has been included in the Support package itself by the name of DividerItemDecoration
class. To have a look at the full working sample of Android RecyclerView, please checkout the link below:
After including divider decoration file and using it through the addItemDecoration
method, your app would look something like this:
In the above tutorial, I tried to make a RecyclerView inspired from the Gmail app. Although its not a complete implementation, but it gives a basic idea on how to use RecyclerView in Android. Hope this Android RecyclerView Tutorial helped you. To stay updated with latest Android tutorials and news connect with us on Facebook, Twitter and Google+.
Born in New Delhi, India. A software engineer by profession, an android enthusiast and an evangelist. My motive here is to create a group of skilled developers, who can develop something new and good. Reason being programming is my passion, and also it feels good to make a device do something you want. In a very short span of time professionally I have worked with many tech firms. As of now too, I am employed as a senior engineer in a leading tech company. In total I may have worked on more than 20 projects professionally, and whenever I get spare time I share my thoughts here at Truiton.
You might want to mention something about https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ItemAnimator.html
Definitely a very useful thing
Hi Akash,
Thanks for the suggestion.
Will include in next tut.
Thanks for this cool tutorial.
I keep getting a nullpointer exception on the “myClickListener”, where do I assign it a value?
Hi,
Have a look at the onResume method of RecyclerViewActivity. It is set using the setOnItemClickListener method of MyRecyclerViewAdapter.
Hope this helps.
-Mohit
How can we add Header in RecyclerView? ListView has addHeaderView() method to add the header. Is there any way to add same in RecyclerView?
how to create custom divider?
you can create your own
DividerItemDecoration.java
and use it.Thanks for such an awesome article man.
Awesome Really helpful, and very well explained keep it up Mohit
Hello
Can I after search in database and fill recycler view if text search exist in db, highlight or bold text search?
Thank you
Works fine thank you
this is good artical
but
i want to add click feature in this code
anyone tell me how to Json parsing i use navigation drawer activity and i have json API but i am unable to fetch JSON data please tell me.
A nice tutorial. Thanks for posting
Really Great tut.
Just how to open a new activity clicking an item.I would like to open activity one by clicking item one and open activity two by clicking item two ?
Great Thanks for your help
Thanks a lot, your tutorial is very helpful
Thank You