Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

This tutorial describes how to use the RecylerView widget in Android applications.

1. Android and list or grids

1.1. Using lists or grids in Android

The display of elements in a list or grids is a very common pattern in mobile applications. The user sees a collection of items and can scroll through them. The collection of items can be a list, a grid or another structured representations of data. Such an activity is depicted in the following picture.

Listview example

The user interacts with the collection of items via touch events or the toolbar. Individual items can be selected. This selection may update the toolbar or may trigger a detailed screen based on the selection. The following graphic sketches that.

Listview example

1.2. Using RecyclerView

The RecyclerView class supports the display of a collection of data.

It is a modernized version of the ListView and the GridView classes provided by the Android framework. Recycler view addresses several issues that the existing widgets have. It enforced a programming style that results in good performance. It also comes with default animations for removing and adding elements.

RecyclerView allow to use different layout managers for positioning items.

Recycler view uses a ViewHolder to store references to the views for one entry in the recycler view. A ViewHolder class is a static inner class in your adapter which holds references to the relevant views. With these references your code can avoid the time-consuming findViewById() method to update the widgets with new data.

1.3. Adapters

An adapter manages the data model and adapts it to the individual entries in the widget. It extends the RecyclerView.Adapter class and is assigned to the recycler view via the RecyclerView.setAdapter method. The input to the adapter of an recycler view can be any arbitrary Java objects. Based on this input the adapter must return the total number of items via its getItemCount() method.

The adapter prepares the layout of the items by inflating the correct layout for the individual data elements. This work is done in the onCreateViewHolder method. It returns an object of type ViewHolder per visual entry in the recycler view.

This instance is used to access the views in the inflated layout. The onCreateViewHolder method is only called then a new view must be created.

Every visible entry in a recycler view is filled with the correct data model item by the adapter. Once a data item becomes visible, the adapter assigns this data to the individual widgets which he inflated earlier. This work in done in the onBindViewHolder method.

For example, an entry in a list may have an image on the left side and two text lines in the middle as depicted in the following graphic.

Recycler view example layout

A layout file for a such a line might look like the following.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="6dip"
        android:contentDescription="TODO"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/secondLine"
        android:layout_width="fill_parent"
        android:layout_height="26dip"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_toRightOf="@id/icon"
        android:ellipsize="marquee"
        android:maxLines="1"
        android:text="Description"
        android:textSize="12sp" />

    <TextView
        android:id="@+id/firstLine"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/secondLine"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_alignWithParentIfMissing="true"
        android:layout_toRightOf="@id/icon"
        android:gravity="center_vertical"
        android:text="Example application"
        android:textSize="16sp" />

</RelativeLayout>

1.4. Gradle dependency to use recycler view

The RecyclerView widget is delivered as library and can be used as of API 7 level or higher. Add the a dependency to the latest version of this library to your Gradle build file to use it.

dependencies {
    ...
    compile "com.android.support:recyclerview-v7:25.1.1"
}

1.5. Default layout manager

The layout manager decides how the data in the RecyclerView is displayed. The recycler view library provides the following build-in layout managers.

  • LinearLayoutManager shows items in a vertical or horizontal scrolling list.

  • GridLayoutManager shows items in a grid.

  • StaggeredGridLayoutManager shows items in a staggered grid.

1.6. Relevant implementation classes to use RecyclerView

The implementation of RecyclerView requires a few classes to be implemented. The most important classes are listed in the following table

Table 1. Important classes of the RecyclerView API
Class Purpose Optional

Adapter

Provides the data and responsible for creating the views for the individual entry

Required

ViewHolder

Contains references for all views that are filled by the data of the entry

Required

LayoutManager

Contains references for all views that are filled by the data of the entry

Required, but default implementations available

ItemDecoration

Responsible for drawing decorations around or on top of the view container of an entry

Default behavior, but can be overridden

ItemAnimator

Responsible to define the animation if entries are added, removed or reordered

Default behavior, but can be overridden

You can also provide your custom implementations for the layout managers and animations.

1.7. Handling click events in recycler view

Touch events, like clicking should be handled by the views in the recycler view. If the view should trigger something in the object in which it is used (activity or fragment), you can pass via the constructor of the adapter to it. This allows the adapter to store a reference to the object and call its methods for feedback.

1.8. Layouts in recycler view

The adapter needs to provide the view hierarchy for each entry. Typical this is done by inflating an XML layout file.

Use wrap_content or ?android:attr/listPreferredItemHeight for the height of the view container for the row.

<LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeight">
        <!-- views contained in each line -->
</LinearLayout>

This root of the layout is typically a ViewGroup (layout manager) and contains several other views. The following graphic shows a list with different layouts for odd and even rows.

Adapter provides data and defines the layout per row

Within the getItemViewType method the recycler view determines which type should be used for data. The framework calls automatically the onCreateViewHolder method if needed for this type. In this method you inflate the correct layout for the type and return a fitting view holder.

1.9. Custom animations

To customize the animations in the RecyclerView, implement your own animation by extending the RecyclerView.ItemAnimator class and use the RecyclerView.setItemAnimator() method to assign it to your widget.

1.10. Filtering and sorting

Filtering and sorting of the data is handled by the adapter. You need to implement the logic in your custom adapter implementation.

1.11. Data updates in the adapter

The notifyItemInserted(position) method on the adapter can be used to notify the view that a new entry has been inserted at a certain position.

The notifyItemRemoved(position); method can be used to notify the view that a entry has been deleted in a certain position.

1.12. Swipe support for RecyclerView

The ItemTouchHelper class that makes swipe-to-dismiss and drag-and-drop simple to implement. Implement the onMove method for drag and drop and the onSwiped for swip support.

See Add swipe to dismiss support for an example implementation.

2. Exercise: Using RecylerView in a new Android application

In this exercise you create a project which uses the RecyclerView class to display a list.

RecyclerView example

2.1. Create projects and add the Gradle dependency

Create a new Android project using the com.vogella.android.recylerview top level package name.

Add a required dependency to your Gradle build file. See Gradle dependency to use recycler view for details.

2.2. Create layout files

Create or update the a layout file called activity_main.xml so that it contains the RecyclerView

<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="${relativePackage}.${activityClass}" >

    <!-- A RecyclerView with some commonly used attributes -->

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

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="12dp"
        android:layout_marginRight="12dp"
        android:elevation="2dp"
        android:src="@drawable/ic_add_circle" />

</RelativeLayout>

Note: The ImageView has the android:elevation attribute set, this instructs Android to draw a shadow for it.

Also create a layout to use in each item.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="6dip"
        android:contentDescription="TODO"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/secondLine"
        android:layout_width="fill_parent"
        android:layout_height="26dip"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_toRightOf="@id/icon"
        android:ellipsize="marquee"
        android:maxLines="1"
        android:text="Description"
        android:textSize="12sp" />

    <TextView
        android:id="@+id/firstLine"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/secondLine"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_alignWithParentIfMissing="true"
        android:layout_toRightOf="@id/icon"
        android:gravity="center_vertical"
        android:text="Example application"
        android:textSize="16sp" />

</RelativeLayout>

Create the following adapter class.

package com.vogella.android.databinding;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;

import java.util.Arrays;
import java.util.List;

public class SecondActivity extends Activity implements MainActivityContract.View {

    private RecyclerView recyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_main);
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        recyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(mLayoutManager);

        List<String> items = Arrays.asList("Test1", "Test2"); // here the example data is created

        // define an adapter
        mAdapter = new MyAdapter(items);
        recyclerView.setAdapter(mAdapter);
    }

    @Override
    public void showData(TemperatureData temperatureData) {
        String celsius = temperatureData.getCelsius();
        Toast.makeText(this, celsius, Toast.LENGTH_SHORT).show();
    }
}

Now you can configure your recycler view in your activity.

public class MyActivity extends Activity {
    private RecyclerView recyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        recyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(mLayoutManager);

        List<String> items = Arrays.asList("Test1", "Test2");

        // define an adapter
        mAdapter = new MyAdapter(items);
        recyclerView.setAdapter(mAdapter);
    }
    ...
}

2.3. Add swipe to dismiss support

Add the following code to the end of your onCreate method in your activity to configure swipe for your data model.

 ItemTouchHelper.SimpleCallback simpleItemTouchCallback =
                new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
                items.remove(viewHolder.getAdapterPosition());
                adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
            }
        };

        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
        itemTouchHelper.attachToRecyclerView(mRecyclerView);

3. About this website

4. Recycler view resources

4.1. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2016 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.