Android RecyclerView With Scrolling Behaviour

By | November 6, 2015

Android Lollipop highly focused on rich user experience which is called as Material Design , And this version features a new widget called RecyclerView . RecyclerView is an extremely powerful and flexible way to show a list, grid, or any view of a large set of data that can be recycled and scrolled very efficiently. One advantage over ListView or GridView is the built in support for animations as items are added, removed, or repositioned .

Build Gradle

Add the following lines to the dependencies section in your project’s build.grade file.

file : build.gradle

dependencies {
    compile fileTree(dir: ‘libs’, include: [‘*.jar’])
    compile ‘com.android.support:appcompat-v7:23.0.1’
    compile ‘com.android.support:design:23.0.1’
    compile ‘com.android.support:recyclerview-v7:23.0.1’
}

I this tutorial we will create RecyclerView in one of Tabs of TabLayout , Creating TabLayout is outside the scope of this tutorial ,In the previous tutorial I have covered how to Create TabLayout you can refer for it .

XML Layout

Create  XML layout file in res/layout and name it tab_one_fragment.xml and Add RecyclerView inside RelativeLayout.

file : tab_one_fragment.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<RelativeLayout
    xmlns:android=”http://schemas.android.com/apk/res/android”
    xmlns:app=”http://schemas.android.com/apk/res-auto”
    android:layout_width=”match_parent”
    android:layout_height=”match_parent”
    android:background=”@color/fragment_bg“>

    <android.support.v7.widget.RecyclerView
        android:id=”@+id/recyclerview”
        android:layout_width=”match_parent”
        android:layout_height=”match_parent”
        app:layout_behavior=”@string/appbar_scrolling_view_behavior”/>

</RelativeLayout>

Create  XML Layout file in res/layout and name it list_row.xml , This Layout defines the layout for Items of RecyclerView . Here In this example we have a TextView inside LinearLayout .

file : list_row.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout
    xmlns:android=”http://schemas.android.com/apk/res/android”
    android:orientation=”vertical”
    android:padding=”16dp”
    android:layout_width=”match_parent”
    android:layout_height=”56dp”>

    <TextView
        android:id=”@+id/list_item”
        android:layout_width=”wrap_content”
        android:layout_height=”wrap_content”/>

</LinearLayout>

RecyclerView Adapter

Create a Adapter That RecyclerView Can Use .

  • Create A Class RVAdapter and this class Must Extend RecyclerView.Adapter. This adapter follows the view holder design pattern, which means that you have to define a custom class that extends RecyclerView.ViewHolder (This pattern minimizes the number of calls to the costly findViewById method.) .
  • So Create a  ItemViewHolder Inside the  RVAdapter and  this class Must Extend  RecyclerView.ViewHolder .
  • we already defined the XML layout list_row.xml , We are going to reuse that layout now. Inside the constructor of our custom ViewHolder, initialize the views that belong to the items of our RecyclerView. 
  • Next, add a constructor to the custom adapter so that it has a handle to the data that the RecyclerView displays , As our data is in the form of a List<String> . 

RecyclerView.Adapter has three abstract methods that we must override .

  1. getItemCount() :  This method return the number of items present in the data
  2. onCreateViewHolder() : Inside this method we specify the layout that each item of the RecyclerView should use. This is done by inflating the layout using LayoutInflater, passing the output to the constructor of the custom ViewHolder.
  3. onBindViewHolder() : This Method This method is very similar to the getView method of a ListView’s adapter. In our example, here’s where you have to set the String values to TextView. 

file : RVAdapter.java

package com.tutorialsbuzz.recyclerview.TabFragments;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.tutorialsbuzz.recyclerview.R;
import java.util.List;

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.ItemViewHolder> {

    private List<String> mItems;
 
    public RVAdapter(List<String> mItems) {
        this.mItems = mItems;
    }

    public class ItemViewHolder extends RecyclerView.ViewHolder {

        private TextView mTextView;

        public ItemViewHolder(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView.findViewById(R.id.list_item);
        }
    }

    @Override
    public void onBindViewHolder(ItemViewHolder itemViewHolder, int i) {
        itemViewHolder.mTextView.setText(mItems.get(i));
    }

    @Override
    public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, viewGroup, false);
        ItemViewHolder itemViewHolder = new ItemViewHolder(view);
        return itemViewHolder;
    }

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

Fragment

1.  Create a TabOneFragment which extends Fragment .
2.  Inside the onCreateView method get the reference to recyclerview and set the LayoutLayout .

Setting LayoutManager .
Unlike a ListView, a RecyclerView needs a LayoutManager to manage the positioning of its items
you could simply use one of the predefined LayoutManager subclasses:

  • LinearLayoutManager.
  • GridLayoutManager.
  • StaggeredGridLayoutManager.

In this tutorial, I am going to use a LinearLayoutManager. This LayoutManager subclass by default, make your RecyclerView look like a ListView.

3. Inside the OnActivityCreate method call to setAdpter on recyclerview reference and pass the object of the Custom Adapter.

file : TabOneFragment.java

package com.tutorialsbuzz.recyclerview.TabFragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.tutorialsbuzz.recyclerview.R;
import java.util.ArrayList;

public class TabOneFragment extends Fragment {

    private RecyclerView recyclerview;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.tab_one_fragment, container, false);

        recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        recyclerview.setLayoutManager(layoutManager);

        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        ArrayList<String> items = new ArrayList<String>();
        for (int i = 0; i < 50; i++) {
            items.add(“TextView_” + i);
        }

        RVAdapter adapter = new RVAdapter(items);
        recyclerview.setAdapter(adapter);

    }

}

Scrolling Behaviour 

As I already mentioned at the beginning of the tutorial that I am Adding RecyclerView to one of Tabs of TabLayout , Creating Tablayout is out of the scope of this tutorial , you can find tutorial for it at
Android TabLayout .

The Complete XML Layout of the Activity which contains Coordinate layout as parent view and inside we have AppBarLayout and ViewPager.

<android.support.design.widget.CoordinatorLayout     xmlns:android=”http://schemas.android.com/apk/res/android”
    xmlns:app=”http://schemas.android.com/apk/res-auto”
    android:layout_width=”match_parent”
    android:layout_height=”match_parent”>

    <android.support.design.widget.AppBarLayout
        android:layout_width=”match_parent”
        android:layout_height=”wrap_content”
        android:theme=”@style/ThemeOverlay.AppCompat.Dark”>

        <android.support.v7.widget.Toolbar
            android:id=”@+id/toolbar”
            android:layout_width=”match_parent”
            android:layout_height=”?attr/actionBarSize”
            android:background=”?attr/colorPrimary”
            app:layout_scrollFlags=”scroll|enterAlways” />

        <android.support.design.widget.TabLayout
            android:id=”@+id/tablayout”
            android:layout_width=”match_parent”
            android:layout_height=”wrap_content”
            app:tabGravity=”fill”
            app:tabMode=”fixed” />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id=”@+id/viewpager”
        android:layout_width=”match_parent”
        android:layout_height=”match_parent” />

</android.support.design.widget.CoordinatorLayout>

  • In the above XML Layout we have Toolbar and TabLayout inside AppBarLayout 
  • The AppBarLayout allows the Toolbar and other views (such as tabs provided by TabLayout) to react to scroll events in a sibling view marked with a ScrollingViewBehaviour .
  • In the Above XML file ViewPager is a sibling view to appbar and to register the scroll behaviour  the ViewPager is marked with a  @string/appbar_scrolling_view_behavior .
  • When the user scrolls through the RecyclerView, the AppBarLayout responds by using its children’s scroll flags to control how they enter (scroll on screen) and exit (scroll off screen).

Flags include : 
  1. scroll: this flag should be set for all views that want to scroll off the screen – for views that do not use this flag, they’ll remain pinned to the top of the screen.
  2. enterAlways: this flag ensures that any downward scroll will cause this view to become visible, enabling the ‘quick return’ pattern .
  3. enterAlwaysCollapsed: When your view has declared a minHeight and you use this flag, your View will only enter at its minimum height (i.e., ‘collapsed’), only re-expanding to its full height when the scrolling view has reached it’s top.
  4. exitUntilCollapsed: this flag causes the view to scroll off until it is ‘collapsed’ (its minHeight) before exiting .
Note : all views using the scroll flag must be declared before views that do not use the flag.This ensures that all views exit from the top, leaving the fixed elements behind.
In our app we use the scroll and enterAlways flags on the Toolbar which will result in the Toolbar scrolling off screen when scrolling upwards and come back on screen on the downward scroll. Notice the use of app:layout_behavior=”@string/appbar_scrolling_view_behavior” on the ViewPager. The support library contains a special string resource @string/appbar_scrolling_view_behavior that maps to AppBarLayout. ScrollingViewBehavior, which is used to notify the AppBarLayout when scroll events occur on a particular view.  The behavior must be established on the view that triggers the event. 

More Tutorial On RecyclerView

  1. RecyclerView Item Click Listener With Ripple Effect.
  2. RecyclerView With CardView.
  3. RecyclerView Item Filter.
  4. RecyclerView Item Filter With Animation.