Android RecyclerView With Header And Footer Example | Sticky Fixed Multi Column

android listview sticky header like iphone, android recyclerview sticky header like iphone, android listview with header and footer, android recyclerview with header and footer

Android RecyclerView Header tutorial will provide different examples like the below table.

Table of Content

1. Android RecyclerView With Header And Footer Example | Sticky Fixed

2. Android RecyclerView Sticky Header Like iPhone | Pinned Header

3. Android RecyclerView Multi-Column With Sticky Header Example Tutorial

4. Android RecyclerView Section Header Example | Group By Header





Android RecyclerView With Header And Footer Example is what you are reading.

In this example, I will show you how to add sticky header and footer to the RecyclerView.

Android do not have built in method to make recyclerview with fixed header and footer.

While ListView have methods like addHeaderView() and addFooterView() methods which simplifies this process.

You may need to have fixed or sticky layout at the starting as well as ending point of the recyclerview to show useful information.

For example, the order summary window of the online food ordering app.

In this screen, you use recyclerview to show different food items with their name, quantity and price.

Here, you can show restaurant name at the header and total of price and quantity at the footer.

See RecyclerView Header and Footer

Step 1. Write Dependencies

Add the following lines in your build.gradle(Module:app) file

 implementation 'com.android.support:recyclerview-v7:27.1.1'
 implementation 'com.android.support:cardview-v7:27.1.1'

Above lines will enable us to use RecyclerView and CardView in our android studio project.

Step 2. XML files for header and footer

To make a fully customizable header and footer, we need to make XML files for both of them.

So make a new XML resource file under res->layout directory.

Name of this file should be rv_header.xml and add the below code in it.

<?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">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="10dp"
        android:id="@+id/htv"
        android:padding="10dp"
        android:textColor="#fff"
        android:textStyle="bold"
        android:gravity="center"
        android:textSize="20dp"
        android:text="I am Header View of RecyclerView. Add ImageView, Button etc widget here."
        android:background="#3a0ae7"/>

</LinearLayout>

I have taken one textview in this header file.

You can add imageview, videoview, button etc. UI widget to make it more attractive.

Now under same directory, create another XML file named rv_footer.xml

Write down following source code in rv_footer.xml

<?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">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:id="@+id/ftv"
        android:padding="10dp"
        android:textColor="#fff"
        android:textStyle="bold"
        android:gravity="center"
        android:textSize="20dp"
        android:text="I am Footer View of Recyclerview. Add ImageView, Button etc widget here."
        android:background="#e7660a"/>

</LinearLayout>
  • Again, I am adding just textview in this file. This file is also fully customizable and you can add styles and widgets to it.

Step 3. RecyclerView Specific File

Now it is time to make an XML file which helps to create views of every row of the recyclerview.

Make a new XML resource file under res->layout directory.

Give it a name single_item.xml and write the below code

<?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.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="10dp"
        card_view:cardCornerRadius="4dp">

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp"
            android:background="@color/colorAccent"
            android:gravity="center_vertical"
            android:paddingLeft="10dp"
            android:text="111"
            android:textColor="#fff"
            android:textSize="20sp"
            android:textStyle="bold" />

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

</LinearLayout>
  • I have written cardview code as a parent of the textview.
  • It will create a cardview section which makes recyclerview more attractive.

Step 4. Model Code

Let us create a model class for data maintenance.

Make a new JAVA class and give it a name HeaderModel.java

Following is the code block for HeaderModel.java

public class HeaderModel {

    private String viewType;
    private String text;

    public String getViewType(){
        return viewType;
    }

    public void setViewType(String viewType){
        this.viewType = viewType;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

There are two types of data. One is the viewType and other is text.

viewType means a type of the item, whether it is header, footer or normal.

text means simply a value of the recyclerview item.

This class uses separate getter and setter methods for both variables.

Step 5. Adapter of RecyclerView

Adapter will help us to populate our RecyclerView in correct manner.

Prepare a new class named HFAdapter.java and add the below source code

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;

public class HFAdapter extends RecyclerView.Adapter<HFAdapter.MyViewHolder> {

    public static final int Header = 1;
    public static final int Normal = 2;
    public static final int Footer = 3;

    private LayoutInflater inflater;
    private ArrayList<HeaderModel> headerModelArrayList;;

    public HFAdapter(Context ctx,  ArrayList<HeaderModel> headerModelArrayList){

        inflater = LayoutInflater.from(ctx);
        this.headerModelArrayList = headerModelArrayList;
    }

    @Override
    public int getItemViewType(int position) {

        if(headerModelArrayList.get(position).getViewType().equals("header")){
            return Header;
        }
        else if(headerModelArrayList.get(position).getViewType().equals("footer")){
            return Footer;
        }
        else {
            return Normal;
        }

    }

    @Override
    public HFAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view ;
        MyViewHolder holder;

        switch (viewType)
        {
            case Normal:
                view = inflater.inflate(R.layout.single_item, parent, false);
                holder = new MyViewHolder(view , Normal);
                break;

            case Header:
                view = inflater.inflate(R.layout.rv_header, parent, false);
                holder = new MyViewHolder(view , Header);
                break;
            case Footer:

                view = inflater.inflate(R.layout.rv_footer, parent, false);
                holder = new MyViewHolder(view , Footer);
                break;

            default:

                view = inflater.inflate(R.layout.single_item, parent, false);
                holder = new MyViewHolder(view , Normal);
                break;
        }




        return holder;
    }

    @Override
    public void onBindViewHolder(HFAdapter.MyViewHolder holder, int position) {

        if(headerModelArrayList.get(position).getViewType().equals("header")){
            //holder.tvProduct.setText(" Item No : " + headerModelArrayList.get(position).getText());
        }
        else if(headerModelArrayList.get(position).getViewType().equals("footer")){
           // holder.tvProduct.setText(" Item No : " + headerModelArrayList.get(position).getText());
        }
        else {
            holder.tvProduct.setText(" Item No : " + headerModelArrayList.get(position).getText());
        }


    }

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

    class MyViewHolder extends RecyclerView.ViewHolder{

        private TextView tvProduct;

        public MyViewHolder(View itemView, int viewType) {
            super(itemView);

            if(viewType == Normal){
                tvProduct = (TextView) itemView.findViewById(R.id.tv);
            }
       }

    }
}

Read the below code

 public static final int Header = 1;
 public static final int Normal = 2;
 public static final int Footer = 3;

 private LayoutInflater inflater;
 private ArrayList<HeaderModel> headerModelArrayList;;

First three integers are constants which stands for Header, Footer or Normal.

Then compiler will create object of LayoutInflater class.

Last line will create an arraylist of objects of HeaderModel class.

Look at the below constructor

 public HFAdapter(Context ctx,  ArrayList<HeaderModel> headerModelArrayList){

        inflater = LayoutInflater.from(ctx);
        this.headerModelArrayList = headerModelArrayList;
    }
  • Constructor will get context and arraylist into the parameter.
  • Then compiler will initialize them both.

Below method,

 @Override
    public int getItemViewType(int position) {

        if(headerModelArrayList.get(position).getViewType().equals("header")){
            return Header;
        }
        else if(headerModelArrayList.get(position).getViewType().equals("footer")){
            return Footer;
        }
        else {
            return Normal;
        }

    }

This method will decide whether the row item is Header, Footer or Normal.

Look at the following code

 @Override
    public HFAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view ;
        MyViewHolder holder;

        switch (viewType)
        {
            case Normal:
                view = inflater.inflate(R.layout.single_item, parent, false);
                holder = new MyViewHolder(view , Normal);
                break;

            case Header:
                view = inflater.inflate(R.layout.rv_header, parent, false);
                holder = new MyViewHolder(view , Header);
                break;
            case Footer:

                view = inflater.inflate(R.layout.rv_footer, parent, false);
                holder = new MyViewHolder(view , Footer);
                break;

            default:

                view = inflater.inflate(R.layout.single_item, parent, false);
                holder = new MyViewHolder(view , Normal);
                break;
        }
        return holder;
    }

Above method will inflate the required XML file to create the view of the row item.

If it is a header then compiler will inflate rv_header.xml , for footer rv_footer.xml, and single_item.xml for normal row.

Now read the below code

 @Override
    public void onBindViewHolder(HFAdapter.MyViewHolder holder, int position) {

        if(headerModelArrayList.get(position).getViewType().equals("header")){
            //holder.tvProduct.setText(" Item No : " + headerModelArrayList.get(position).getText());
        }
        else if(headerModelArrayList.get(position).getViewType().equals("footer")){
           // holder.tvProduct.setText(" Item No : " + headerModelArrayList.get(position).getText());
        }
        else {
            holder.tvProduct.setText(" Item No : " + headerModelArrayList.get(position).getText());
        }


    }
  • Compiler will check if the item at given position is header, footer or normal.
  • According to that if condition, compiler will set the text.

Step 6. Final Coding

We at the last part of this example. We will update activity_main.xml and MainActivity.java here.

Code block for activity_main.xml looks like the below

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="20dp"
        android:id="@+id/recycler">

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

</android.support.constraint.ConstraintLayout>

I have just taken one recyclerview in the main file.

Add the following code structure in MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private HFAdapter hfAdapter;

    private ArrayList<HeaderModel> headerModelArrayList;

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

        recyclerView = findViewById(R.id.recycler);

        headerModelArrayList = new ArrayList<>();
        dataSet();

        hfAdapter = new HFAdapter(this,headerModelArrayList);
        recyclerView.setAdapter(hfAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));


    }

    private void dataSet(){

        for (int i = 0; i < 18; i++ ){

            if (i == 0){

                HeaderModel headerModel= new HeaderModel();
                headerModel.setViewType("header");
                headerModelArrayList.add(headerModel);

            }else if( i == 17){
                HeaderModel headerModel= new HeaderModel();
                headerModel.setViewType("footer");
                headerModelArrayList.add(headerModel);

            }else {
                HeaderModel headerModel= new HeaderModel();
                headerModel.setViewType("normal");
                headerModel.setText("Item Number : "+i);
                headerModelArrayList.add(headerModel);
            }

        }

    }

}

Reading Main Activity

Consider the below source code

 private RecyclerView recyclerView;
 private HFAdapter hfAdapter;
 private ArrayList<HeaderModel> headerModelArrayList;

First one is making an object of the recyclerview.

Second is making the object of HFAdapter class.

Third one will create an arraylist with the objects of the HeaderModel class.

In onCreate() method, compiler will call dataSet() method.

Code for dataSet() method is as the following

  private void dataSet(){

        for (int i = 0; i < 18; i++ ){

            if (i == 0){

                HeaderModel headerModel= new HeaderModel();
                headerModel.setViewType("header");
                headerModelArrayList.add(headerModel);

            }else if( i == 17){
                HeaderModel headerModel= new HeaderModel();
                headerModel.setViewType("footer");
                headerModelArrayList.add(headerModel);

            }else {
                HeaderModel headerModel= new HeaderModel();
                headerModel.setViewType("normal");
                headerModel.setText("Item Number : "+i);
                headerModelArrayList.add(headerModel);
            }

        }

    }

This method generating the data to populate the arraylist.

Compiler will first run a for loop for the number of times equals to the number of recyclerview items + 2 (header and footer)

If the value if i is zero, it means that it is the first row of recyclerview.

Here, first row is the header of the recyclerview.

From second row to last second rows are the recyclerview items and here, compiler will execute the (else if) part.

Then, last row of the Recyclerview is the footer so compiler will execute the (else) part.





2. Android RecyclerView Sticky Header Like iphone | Pinned Header

Welcome to Android RecyclerView Sticky Header Like iphone Example.

We are going to develop a recyclerview with pinned headers in this tutorial.

You may have watched this concept of sticky or pinned header in iphone or ios.

Sticky header will stick at the top side of the recyclerview.

Now header can be one or more depending upon the type of the children items of recyclerview.

If there are more than one header, than header will be replace by another header when user scroll up all the items of the old header.

Android’s built in system do not provide any direct method or class to develop this kind of recyclerview.

So we need to use external github library in this example tutorial.

View RecyclerView

Step 1. Fetching Dependency

We will use one github library in this tutorial.

It will allow us to use some classes which are required in this example.

For this, add the below line in build.gradle(Modile:app) file

 implementation 'com.shuhart.stickyheader:stickyheader:1.0.5'
 implementation 'com.android.support:recyclerview-v7:27.1.1'

First line will integrate third party library.

Other one will fetch the required classes to use RecyclerView.

Step 2. Layout For Header And Children

In this example, we need to create two different layout XML files.

One will represent the header and another will represent children items.

Create a new file in res->layout directory and give it a name recycler_view_header_item.xml

Add the below code in recycler_view_header_item.xml file

<?xml version="1.0" encoding="utf-8"?>
<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="?listPreferredItemHeight">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/darker_gray"
        android:gravity="center_vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        tools:text="Header" />
</RelativeLayout>
  • Just one textview in the above file. You can also add imageview and other widget as per your requirements.

Make another XML file named recycler_view_item.xml and copy the following in it

<?xml version="1.0" encoding="utf-8"?>
<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="?listPreferredItemHeight">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        android:gravity="center_vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        tools:text="Item" />
</RelativeLayout>

Step 3. New Interface

Create a new Interface and give it a name Section.java

Code structure for interface Section.java is as below

public interface Section {

    boolean isHeader();
    String getName();

    int sectionPosition();
}

We will use this interface to create an arraylist with the objects of two different model classes.

Step 4. Models For Header And Child

Prepare a new JAVA class and name it as ChildModel.java

Write down the following coding lines in ChildModel.java

public class ChildModel implements Section {

    String child;
    private int section;

    public ChildModel(int section) {
        this.section = section;
    }

    public void setChild(String child) {
        this.child = child;
    }

    @Override
    public boolean isHeader() {
        return false;
    }

    @Override
    public String getName() {
        return child;
    }

    @Override
    public int sectionPosition() {
        return section;
    }
}

Now make another class named HeaderModel.java and code for it is as below

public class HeaderModel implements Section {

    String header;
    private int section;

    public HeaderModel(int section) {
        this.section = section;
    }

    public void setheader(String header) {
        this.header = header;
    }

    @Override
    public boolean isHeader() {
        return true;
    }

    @Override
    public String getName() {
        return header;
    }

    @Override
    public int sectionPosition() {
        return section;
    }
}

These model classes are useful for the maintenance of data while populating the RecyclerView.

Models are implementing Section interface and thus it also overrides all the methods of that interface.

Step 5. Section Adapter

Now it is time to write an adapter class for recyclerview.

Make a new class named SectionAdapter.java and write the following lines

import android.annotation.SuppressLint;
import android.content.Context;
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 com.shuhart.stickyheader.StickyAdapter;
import java.util.ArrayList;

public class SectionAdapter extends StickyAdapter<RecyclerView.ViewHolder, RecyclerView.ViewHolder> {

    private ArrayList<Section> sectionArrayList;
    private static final int LAYOUT_HEADER= 0;
    private static final int LAYOUT_CHILD= 1;

    public SectionAdapter(Context context, ArrayList<Section> sectionArrayList){

       // inflater = LayoutInflater.from(context);
       // this.context = context;
        this.sectionArrayList = sectionArrayList;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        if (viewType == LAYOUT_HEADER ) {
            return new HeaderViewholder(inflater.inflate(R.layout.recycler_view_header_item, parent, false));
        }else {
            return new ItemViewHolder(inflater.inflate(R.layout.recycler_view_item, parent, false));
        }
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (sectionArrayList.get(position).isHeader()) {
            ((HeaderViewholder) holder).textView.setText( sectionArrayList.get(position).getName());
        } else {
            ((ItemViewHolder) holder).textView.setText(sectionArrayList.get(position).getName());
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(sectionArrayList.get(position).isHeader()) {
            return LAYOUT_HEADER;
        }else
            return LAYOUT_CHILD;
    }

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

    @Override
    public int getHeaderPositionForItem(int itemPosition) {
        Log.d("seeee",""+itemPosition+"......"+sectionArrayList.get(itemPosition).sectionPosition());
        return sectionArrayList.get(itemPosition).sectionPosition();
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int headerPosition) {
        ((HeaderViewholder) holder).textView.setText( sectionArrayList.get(headerPosition).getName());
    }

    @Override
    public RecyclerView.ViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
        return createViewHolder(parent, LAYOUT_HEADER);
    }

    public static class HeaderViewholder extends RecyclerView.ViewHolder {
        TextView textView;

        HeaderViewholder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.text_view);
        }
    }

    public static class ItemViewHolder extends RecyclerView.ViewHolder {
        TextView textView;

        ItemViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.text_view);
        }
    }
}

Important methods of Adapter

In the constructor of this adapter, we are getting an arraylist with objects of the interface “Section

This arraylist contains the objects of both ChildModel and HeaderModel.

I will explain this arraylist in Main Activity, but for now we will just use it.

Consider the below code

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        if (viewType == LAYOUT_HEADER ) {
            return new HeaderViewholder(inflater.inflate(R.layout.recycler_view_header_item, parent, false));
        }else {
            return new ItemViewHolder(inflater.inflate(R.layout.recycler_view_item, parent, false));
        }
    }

Above method is inflating required XML file : recycler_view_header_item.xml or recycler_view_item.xml

If viewType is header than compiler will inflate recycler_view_header_item.xml file which is representing the header view.

Otherwise it will inflate the recycler_view_item.xml.

Read the following method

 @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (sectionArrayList.get(position).isHeader()) {
            ((HeaderViewholder) holder).textView.setText( sectionArrayList.get(position).getName());
        } else {
            ((ItemViewHolder) holder).textView.setText(sectionArrayList.get(position).getName());
        }
    }

This method is setting the text in the textview.

Compiler will use isHeader() method (from interface) to decide whether the item is header or child.

And according to that, it will select the textview to write the name.

Step 6. Main Activity Files

Last but not least, let us make some necessary changes in the main files.

Source Code block for activity_main.xml should look like the below

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

</android.support.constraint.ConstraintLayout>
  • In this file, I have just taken one recyclerview.

In the MainActivity.java file, write the following source code

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import com.shuhart.stickyheader.StickyHeaderItemDecorator;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private String[] vehicleTypes = new String[]{"Cars", "Bikes",
            "Air Crafts","Old Vehicles"};

    private ArrayList<Section> sectionArrayList;

    private String[] childnames = new String[]{"Range Rover", "Lamborghini",
            "Rolls Royce","Ferrari","Harley davidson","Ducati","BMW","Honda","Boeing","Airbus","Royal Air","Space X","Horse",
            "Elephant","Camel","Donkey","Khachhar","Horse 2","Camel 2","Donkey 2","Tesla","Mercedes"};

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

        RecyclerView recyclerView = findViewById(R.id.recycler_view);

        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        sectionArrayList = new ArrayList<>();
        populateList();

        SectionAdapter adapter = new SectionAdapter(this,sectionArrayList);
        recyclerView.setAdapter(adapter);
        StickyHeaderItemDecorator decorator = new StickyHeaderItemDecorator(adapter);
        decorator.attachToRecyclerView(recyclerView);



    }

    private void populateList(){

        int headerdone = 0, childdone = 0;

        for(int i = 0; i < 26; i++){

            if(i == 0 || i == 5 | i == 10 | i == 15){

                    HeaderModel vehicleModel = new HeaderModel(i);
                    vehicleModel.setheader(vehicleTypes[headerdone]);
                    sectionArrayList.add(vehicleModel);
                    headerdone = headerdone + 1;
            }else {

                    ChildModel childModel = null;
                    if(i == 1 || i == 2 || i ==3 || i == 4){
                        childModel = new ChildModel(0);
                    }else if(i == 6 || i == 7 || i == 8 || i == 9){
                        childModel = new ChildModel(5);
                    }else if(i == 11 || i == 12 || i == 13 || i == 14){
                        childModel = new ChildModel(10);
                    }else {
                        childModel = new ChildModel(15);
                    }

                    childModel.setChild(childnames[childdone]);
                    sectionArrayList.add(childModel);
                    childdone = childdone + 1;
            }
        }

    }
}

Going Inside Main Activity

Consider the below source code

 private String[] vehicleTypes = new String[]{"Cars", "Bikes",
            "Air Crafts","Old Vehicles"};

    private ArrayList<Section> sectionArrayList;

    private String[] childnames = new String[]{"Range Rover", "Lamborghini",
            "Rolls Royce","Ferrari","Harley davidson","Ducati","BMW","Honda","Boeing","Airbus","Royal Air","Space X","Horse",
            "Elephant","Camel","Donkey","Khachhar","Horse 2","Camel 2","Donkey 2","Tesla","Mercedes"};

Second line is creating an arraylist of the objects of the Section Interface.

First line is making a string array which contains the types of the vehicles.

This string array will provide the headers of the RecyclerView.

Third line is also making one string array which is giving us children names for our RecyclerView.

Read the following

   sectionArrayList = new ArrayList<>();
   populateList();

First one is simply initializing the arraylist.

Second one is calling a method populateList()

Code block for populateList() is as the below

  private void populateList(){

        int headerdone = 0, childdone = 0;

        for(int i = 0; i < 26; i++){

            if(i == 0 || i == 5 | i == 10 | i == 15){

                    HeaderModel vehicleModel = new HeaderModel(i);
                    vehicleModel.setheader(vehicleTypes[headerdone]);
                    sectionArrayList.add(vehicleModel);
                    headerdone = headerdone + 1;
            }else {

                    ChildModel childModel = null;
                    if(i == 1 || i == 2 || i ==3 || i == 4){
                        childModel = new ChildModel(0);
                    }else if(i == 6 || i == 7 || i == 8 || i == 9){
                        childModel = new ChildModel(5);
                    }else if(i == 11 || i == 12 || i == 13 || i == 14){
                        childModel = new ChildModel(10);
                    }else {
                        childModel = new ChildModel(15);
                    }

                    childModel.setChild(childnames[childdone]);
                    sectionArrayList.add(childModel);
                    childdone = childdone + 1;
            }
        }

    }

In this method, compiler will create one for loop with 26 iterations.

26 is the number equal to the number of children items + header items.

You should change this number as per the number of children items + header items. in your project.

if condition ( if(i == 0 || i == 5 | i == 10 | i == 15) ) is true when there are headers.

At this time, compiler will create the object of the HeaderModel class and will add it to the arralist.

When the if condition is false, compiler will create the object of the ChildModel class and will add it to the arraylist.

   SectionAdapter adapter = new SectionAdapter(this,sectionArrayList);
        recyclerView.setAdapter(adapter);
        StickyHeaderItemDecorator decorator = new StickyHeaderItemDecorator(adapter);
        decorator.attachToRecyclerView(recyclerView);

Finally, above code will create an object of the adapter class.

And then it will add the adapter object to the RecyclerView.





3. Android RecyclerView Multi Column With Sticky Header Example Tutorial

Today’s bright topic is about Android Recyclerview Multi Column With Sticky Header.

We will create one example with android studio in this tutorial. You will learn to make android cardview with two or more columns.

Multi column recyclerview means that every single row item is having more than one column.

This type of recyclerview creates a table like structure.

In many occasions, you want to make a layout where there are one or more sticky headers and then a table like structure.

For example, to show an order summary at restaurant app, you may have static headers like name of the restaurant.

After that you will show an order in the tabular form using recyclerview.

Here, this tutorial will help you get your goal.

Final UI

Now follow all the below steps to create this example.

Step 1. Having Dependencies

We are going to use recyclerview and cardview here. So we need to add it’s dependencies in

build.gradle(Module :app) file.

Write below lines in build.gradle(Module :app) file.

  implementation 'com.android.support:recyclerview-v7:27.1.1'
  implementation 'com.android.support:cardview-v7:27.1.1'

Above lines will download necessary classes for recyclerview and cardview.

Step 2. Making Recycler Item File

Now we will create one layout file. This file will generate the view structure for each row of recyclerview.

Create a new file named recycler_item.xml in res->layout directory.

Copy the following source code in recycler_item.xml

<?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:orientation="vertical">

    <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        card_view:cardCornerRadius="4dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#e6ed17"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tvProduct"
                android:layout_width="0dp"
                android:layout_height="50dp"
                android:layout_weight="2"
                android:gravity="center"
                android:text="Product Name"
                android:textColor="#000000"
                android:textSize="20sp" />

            <TextView
                android:id="@+id/tvQty"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:text="Quantity"
                android:textColor="#000"
                android:textSize="20sp" />

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

</LinearLayout>

In the above code, I have taken <android.support.v7.widget.cardview> as a parent of the main layout. It will generate card structure.

Under this cardview tag, I have taken one Linearlayout with horizontal orientation.

Now, I have set two Textviews horizontally under this linearlayout.

First textview is for product name and second is for product quantity.

Step 3. Making Food Model

The main purpose behind creating model class is to have proper data set to populate the recyclerview.

Prepare a new java class named FoodModel.java

Add the below code in FoodModel.java

public class FoodModel {

    private String product;
    private int qty;

    public String getProduct() {
        return product;
    }

    public void setProduct(String product) {
        this.product = product;
    }

    public int getQty() {
        return qty;
    }

    public void setQty(int qty) {
        this.qty = qty;
    }
}
  • Above structure includes getter and setter methods for two variables.
  • One variable is for product name and another is for quantity.

Step 3. Preparing Adapter

Let us create adapter class which will provide data to populate the recyclerview.

Make a new java class named FoodAdapter.java

Write down the following coding lines in FoodAdapter.java

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

import java.util.ArrayList;

public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.MyViewHolder> {

    private LayoutInflater inflater;
    private ArrayList<FoodModel> foodModelArrayList;

    public FoodAdapter(Context ctx, ArrayList<FoodModel> foodModelArrayList){

        inflater = LayoutInflater.from(ctx);
        this.foodModelArrayList = foodModelArrayList;
    }

    @Override
    public FoodAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = inflater.inflate(R.layout.recycler_item, parent, false);
        MyViewHolder holder = new MyViewHolder(view);

        return holder;
    }

    @Override
    public void onBindViewHolder(FoodAdapter.MyViewHolder holder, int position) {

        holder.tvProduct.setText(foodModelArrayList.get(position).getProduct());
        holder.tvQty.setText(String.valueOf(foodModelArrayList.get(position).getQty()));
    }

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

    class MyViewHolder extends RecyclerView.ViewHolder{

        private TextView tvProduct, tvQty;

        public MyViewHolder(View itemView) {
            super(itemView);

           tvProduct = (TextView) itemView.findViewById(R.id.tvProduct);
           tvQty = (TextView) itemView.findViewById(R.id.tvQty);

        }

    }
}

Going through above class

First of all, read the below code

 public FoodAdapter(Context ctx, ArrayList<FoodModel> foodModelArrayList){

        inflater = LayoutInflater.from(ctx);
        this.foodModelArrayList = foodModelArrayList;
}

It is the constructor of the adapter class.

It receives context and arraylist from first and second parameter respectively.

ArrayList contains the objects of the FoodModel class.

Consider the next coding lines

 @Override
    public FoodAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = inflater.inflate(R.layout.recycler_item, parent, false);
        MyViewHolder holder = new MyViewHolder(view);

        return holder;
    }
  • Above method will inflate the recycler_item.xml file which we created in Step 2.
  • Compiler will create layout using this recycler_item.xml file for every row.

Step 4. Final Changes in Main Classes

Last thing is to update activity_main.xml and MainActivity.java files.

Replace the existing code of activity_main.xml with the below lines

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:gravity="center"
        android:background="#f1cc7e"
        android:textSize="30sp"
        android:textColor="#000"
        android:text="Aizy Restaurant"
        />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:gravity="center"
        android:background="#c95fae"
        android:textSize="25dp"
        android:textColor="#fdfdfd"
        android:text="Oeder Summary"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#2d1ed4"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:textColor="#fff"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_weight="2"
            android:text="Product Name"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:textColor="#fff"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_weight="1"
            android:text="Quantity"/>

    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="20dp"
        android:id="@+id/recycler">

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


</LinearLayout>

Here, I have taken two textviews at the top and then one linearlayout with horizontal orientation.

First textview is showing the name of the restaurant and second one is the heading of the page.

After linearlayout I have defined our recyclerview.

Now it is time to write the MainActivity.java as per below code

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private String[] Products = new String[]{"Pizza", "Burger", "Pasta", "Salad", "Rice","Sandwich","Chips"};
    private int[] Qty = new int[]{3, 4, 2, 1, 5,8,20};
    private ArrayList<FoodModel> foodModelArrayList;
    private RecyclerView recyclerView;

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

        recyclerView = findViewById(R.id.recycler);

        //foodModelArrayList = new ArrayList<>();
        foodModelArrayList = populateList();

        FoodAdapter foodAdapter = new FoodAdapter(this,foodModelArrayList);
        recyclerView.setAdapter(foodAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));

    }

    private ArrayList<FoodModel> populateList(){

        ArrayList<FoodModel> list = new ArrayList<>();

        for(int i = 0; i < 7; i++){
            FoodModel foodModel = new FoodModel();
            foodModel.setProduct(Products[i]);
            foodModel.setQty(Qty[i]);
            list.add(foodModel);
        }

        return list;
    }

}

Measuring Above Code

Following are the definitions of the required objects.

    private String[] Products = new String[]{"Pizza", "Burger", "Pasta", "Salad", "Rice","Sandwich","Chips"};
    private int[] Qty = new int[]{3, 4, 2, 1, 5,8,20};
    private ArrayList<FoodModel> foodModelArrayList;
    private RecyclerView recyclerView;

First line is making a string array named Products. It includes various product names.

Second line is creating an integer array which holds the quantity of the products.

Third line will prepare an arraylist (foodModelArrayList) with the objects of the FoodModel class.

Last line will simply make an object of recyclerview.

Consider the below line

  foodModelArrayList = populateList();
  • Above line is setting the data in to the foodModelArrayList.
  • Compiler will use populateList() method to generate the data.
  private ArrayList<FoodModel> populateList(){

        ArrayList<FoodModel> list = new ArrayList<>();

        for(int i = 0; i < 7; i++){
            FoodModel foodModel = new FoodModel();
            foodModel.setProduct(Products[i]);
            foodModel.setQty(Qty[i]);
            list.add(foodModel);
        }

        return list;
    }

Above lines are making the populateList() method.

Here, Compiler will create one for loop with seven iterations.

During every iteration, it will create one object of FoodModel class.  Then it will set the product name and quantity to that object.

After this, compiler will simply add that object in the arraylist.





4. Android RecyclerView Section Header Example | Group By Header

Android RecyclerView Section Header Example is the hot topic of today.

We will create a recyclerview which has specific headers among it’s various child items.

Last Output

Section Header

Section header is a particular row item which can categorized recyclerview’s child items.

For example, you are making recyclerview with vehicle’s manufacturer company names.

Here, you can categorize company names with categories like Cars, Bikes, Air crafts etc.

In the first row you will write “Cars” and in the second and third row, you may write “Mercedes” and “Audee“.

In the fourth row you give section header named “Bikes” and you put “Honda” and “Ducati” in Fifth and sixth row of recyclerview. This process continues til the end.

In this example, we will create a recyclerview where all the section header have different layout structure than the normal child row items.

Let us go through all the steps.

Step 1. Build.gradle(Module: app)

We have to add gradle lines to import the required classes of recyclerview and cardview.

Write following in the build.gradle(Module: app) file

implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'

Step 2. Drawable files

Create a drawable resource file named cardview.xml under res->drawable directory

Copy the following code in cardview.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="true">
        <shape android:shape="rectangle">
            <padding
                android:left="4dp"
                android:top="4dp"
                android:right="4dp"
                android:bottom="4dp"
                />
            <gradient android:startColor="#1cb73b" android:endColor="#29ba48" android:angle="270" />

            <corners android:topLeftRadius="4dp" android:topRightRadius="4dp"/>
        </shape>
    </item>

    <item android:state_focused="false"
        >
        <shape android:shape="rectangle">
            <padding
                android:left="4dp"
                android:top="4dp"
                android:right="4dp"
                android:bottom="4dp"
                />

            <gradient android:startColor="#1cb724" android:endColor="#29ba41" android:angle="270" />

            <corners android:topLeftRadius="4dp" android:topRightRadius="4dp" />
        </shape>
    </item>

</selector>

Above file will create specific background for the section header row.

I have given gradient effect with green color shadows in this file.

Make another file named cardview_child.xml and add following code

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="true">
        <shape android:shape="rectangle">
            <padding
                android:left="4dp"
                android:top="4dp"
                android:right="4dp"
                android:bottom="4dp"
                />
            <gradient android:startColor="#901cb7" android:endColor="#8529ba" android:angle="270" />

            <corners android:topLeftRadius="4dp" android:topRightRadius="4dp"/>
        </shape>
    </item>

    <item android:state_focused="false"
        >
        <shape android:shape="rectangle">
            <padding
                android:left="4dp"
                android:top="4dp"
                android:right="4dp"
                android:bottom="4dp"
                />

            <gradient android:startColor="#8832c1" android:endColor="#8541c4" android:angle="270" />

            <corners android:topLeftRadius="4dp" android:topRightRadius="4dp" />
        </shape>
    </item>

</selector>
  • cardview_child.xml file will create the particular background for child rows of recyclerview.

In this file, purple color gradients will make child row more colorful.

Step 3. RecyclerView Row resources

Now we need to create two layout resources file. One for header row and one for child row.

Make a new layout resource file and name it “rv_header.xml” and add the below source code

<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="wrap_content"
    tools:context=".MainActivity">

    <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        card_view:cardCornerRadius="4dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/tv"
                android:height="50dp"
                android:background="@drawable/cardview"
                android:gravity="center_vertical"
                android:paddingLeft="10dp"
                android:text="Header : Vehicle Type"
                android:textColor="#fff"
                android:textStyle="bold"
                android:textSize="30sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/tvHeader"
                android:background="#ece4e4"
                android:text="Bike"
                android:padding="10dp"
                android:textColor="#000"
                android:textSize="25sp"/>


        </LinearLayout>

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

This “rv_header.xml” file will create a layout structure for header file.

Now create another layout resource file named “rv_child.xml”. Following code is for this file.

<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="wrap_content"
    tools:context=".MainActivity">

    <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        card_view:cardCornerRadius="4dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/tv"
                android:height="50dp"
                android:background="@drawable/cardview_child"
                android:gravity="center_vertical"
                android:paddingLeft="10dp"
                android:text="Sub Item"
                android:textColor="#fff"
                android:textStyle="bold"
                android:textSize="30sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/tvChild"
                android:background="#71b9d6"
                android:text="Bike"
                android:padding="10dp"
                android:textColor="#a72b2b"
                android:textSize="25sp"/>


        </LinearLayout>

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

Every child row will use the above code to create it’s layout structure.

Step 4. Model Classes

Create a new class named HeaderModel.java

Add the below source code in it

package com.example.parsaniahardik.recyclerview_section_header;

public class HeaderModel implements MainActivity.ListItem{

    String header;

    public void setheader(String header) {
        this.header = header;
    }

    @Override
    public boolean isHeader() {
        return true;
    }

    @Override
    public String getName() {
        return header;
    }
}

This class contains necessary methods regarding headers of the recyclerview.

In the above code, isHeader() and getName() methods are override because this class implements the ListItem interface which is written in the Main Activity.

isHeader() method returns the boolean value. If the the object is of the HeaderModel class, then it will return true otherwise false.

getName() method will return the name of the string whether it is vehicle type or manufacturer, it does not matter here.

(You will see the use of these two above methods in the adapter class later in this tutorial)

setHeader() method is used to set the name of the header.

Now create a new class and give it a name “ChildModel.java”

Put following code in it

public class ChildModel implements MainActivity.ListItem{

    String child;

    public void setChild(String child) {
        this.child = child;
    }

    @Override
    public boolean isHeader() {
        return false;
    }

    @Override
    public String getName() {
        return child;
    }
}

All three methods present in the above class are similar with the methods of HeaderModel class.

The text which is set and get by various methods are of the child rows name, while in HeaderModel class, the text was about header name.

Step 5. Writing Main Activity

You need to change the Main activity’s code now.

Add below code in activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#9e9191"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="15dp"/>

</LinearLayout>

I have taken recyclerview in the main layout.

Write down the following source code into MainActivity.java class

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private CustomAdapter customAdapter;

    private String[] vehicleTypes = new String[]{"Cars", "Bikes",
            "Air Crafts","Old Vehicles"};

    private ArrayList<ListItem> listItemArrayList;

    private String[] childnames = new String[]{"Range Rover", "Lamborghini",
            "Rolls Royce","Ferrari","Harley davidson","Ducati","BMW","Honda","Boeing","Airbus","Royal Air","Space X","Horse","Elephant","Camel","Donkey"};

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

        listItemArrayList = new ArrayList<>();
        populateList();

        customAdapter = new CustomAdapter(this,listItemArrayList);
        recyclerView.setAdapter(customAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));
    }

    public interface ListItem {
        boolean isHeader();
        String getName();
    }

    private void populateList(){

        int headerdone = 0, childdone = 0;

        for(int i = 0; i < 20; i++){

            if(i == 0 || i == 5 | i == 10 | i == 15){
                HeaderModel vehicleModel = new HeaderModel();
                vehicleModel.setheader(vehicleTypes[headerdone]);
                listItemArrayList.add(vehicleModel);
                headerdone = headerdone + 1;
            }else {
                ChildModel childModel = new ChildModel();
                childModel.setChild(childnames[childdone]);
                listItemArrayList.add(childModel);
                childdone = childdone + 1;
            }
        }

    }
}

Understanding above code

Read the below lines

 private String[] vehicleTypes = new String[]{"Cars", "Bikes",
            "Air Crafts","Old Vehicles"};
 private String[] childnames = new String[]{"Range Rover", "Lamborghini",
            "Rolls Royce","Ferrari","Harley davidson","Ducati","BMW","Honda","Boeing","Airbus","Royal Air","Space X","Horse","Elephant","Camel","Donkey"};

There are two string array variables are there.

First string array variable called vehicleTypes represents the types of the vehicles. These vehicle types are the headers of the recyclerview.

Second string array variable called childnames contains the names of the vehicle manufacture companies. These names are the child rows of the recyclerview.

Interface

HeaderModel.java and ChildModel.java were implementing the ListItem interface. This interface is defined here in the Main Activity.

Following is it’s coding lines

  public interface ListItem {
        boolean isHeader();
        String getName();
    }

It contains two methods so both HeaderModel.java and ChildModel.java classes were overriding these methods.

Populating RecyclerView Data

Our data for header and child rows are present in the two strings variables as we have just shown above.

Now we need to convert this data in the arraylist of interface objects to pass them into the adapter class.

Following method will do this for us

 private void populateList(){

        int headerdone = 0, childdone = 0;

        for(int i = 0; i < 20; i++){

            if(i == 0 || i == 5 | i == 10 | i == 15){
                HeaderModel vehicleModel = new HeaderModel();
                vehicleModel.setheader(vehicleTypes[headerdone]);
                listItemArrayList.add(vehicleModel);
                headerdone = headerdone + 1;
            }else {
                ChildModel childModel = new ChildModel();
                childModel.setChild(childnames[childdone]);
                listItemArrayList.add(childModel);
                childdone = childdone + 1;
            }
        }

    }

In the RecyclerView, first row will represent the Header name. Then next four rows will be child rows.

As per this calculations, First, Sixth, eleventh and sixteenth rows of the recyclerview will be the header.

So in the above code, if condition will be true for First, Sixth, eleventh and sixteenth iterations of the for loop.

When the if condition is true, an object of the HeaderModel class is created, populated with the name and then it is inserted into the arraylist of interface (which is listItemArrayList).

When the if condition is false, an object of the ChildModel class is created, populated with name and then it is inserted in the arraylist of interface (which is listItemArrayList).

After the successful call of the populateList() method, listItemArrayList passed into the constructor of the Adapter class using below lines

customAdapter = new CustomAdapter(this,listItemArrayList);

Step 6. Custom Adapter

Now finally, we are at the adapter class to fill the recyclerview.

Create a new class named CustomAdapter.java

Add the below code in it

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;

public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int LAYOUT_HEADER= 0;
    private static final int LAYOUT_CHILD= 1;

    private LayoutInflater inflater;
    private Context context;
    private ArrayList<MainActivity.ListItem> listItemArrayList;

    public CustomAdapter(Context context,ArrayList<MainActivity.ListItem> listItemArrayList){

        inflater = LayoutInflater.from(context);
        this.context = context;
        this.listItemArrayList = listItemArrayList;
    }

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

    @Override
    public int getItemViewType(int position)
    {
        if(listItemArrayList.get(position).isHeader()) {
            return LAYOUT_HEADER;
        }else
            return LAYOUT_CHILD;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        RecyclerView.ViewHolder holder;
        if(viewType==LAYOUT_HEADER){
            View view = inflater.inflate(R.layout.rv_header, parent, false);
            holder = new MyViewHolderHeader(view);
        }else {
            View view = inflater.inflate(R.layout.rv_child, parent, false);
             holder = new MyViewHolderChild(view);
        }


        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {

        if(holder.getItemViewType()== LAYOUT_HEADER)
        {
            MyViewHolderHeader vaultItemHolder = (MyViewHolderHeader) holder;
            vaultItemHolder.tvHeader.setText(listItemArrayList.get(position).getName());
        }
        else {

            MyViewHolderChild vaultItemHolder = (MyViewHolderChild) holder;
            vaultItemHolder.tvchild.setText(listItemArrayList.get(position).getName());

        }

    }


    class MyViewHolderHeader extends RecyclerView.ViewHolder{

        TextView tvHeader;

        public MyViewHolderHeader(View itemView) {
            super(itemView);

            tvHeader = (TextView) itemView.findViewById(R.id.tvHeader);
         }

    }

    class MyViewHolderChild extends RecyclerView.ViewHolder{

        TextView tvchild;

        public MyViewHolderChild(View itemView) {
            super(itemView);

            tvchild = (TextView) itemView.findViewById(R.id.tvChild);
        }

    }

}

Explanation

Read the below code

  @Override
    public int getItemViewType(int position)
    {
        if(listItemArrayList.get(position).isHeader()) {
            return LAYOUT_HEADER;
        }else
            return LAYOUT_CHILD;
    }

We are deciding whether the view of the row should be header view or child view in the above method.

We are using isHeader() method for this purpose.

LAYOUT_HEADER and LAYOUT_CHILD are the integer constants.

Consider below codes of classes

class MyViewHolderHeader extends RecyclerView.ViewHolder{

        TextView tvHeader;

        public MyViewHolderHeader(View itemView) {
            super(itemView);

            tvHeader = (TextView) itemView.findViewById(R.id.tvHeader);
         }

    }

    class MyViewHolderChild extends RecyclerView.ViewHolder{

        TextView tvchild;

        public MyViewHolderChild(View itemView) {
            super(itemView);

            tvchild = (TextView) itemView.findViewById(R.id.tvChild);
        }

    }

Two classes are defined in the above code.

First one represents the Header and second one is for Child row.

We are just declaring the textviews for header and child row in the above classes.

Now consider the following code

 @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {

        if(holder.getItemViewType()== LAYOUT_HEADER)
        {
            MyViewHolderHeader vaultItemHolder = (MyViewHolderHeader) holder;
            vaultItemHolder.tvHeader.setText(listItemArrayList.get(position).getName());
        }
        else {

            MyViewHolderChild vaultItemHolder = (MyViewHolderChild) holder;
            vaultItemHolder.tvchild.setText(listItemArrayList.get(position).getName());

        }

    }

We will set the textview value in onBingViewHolder method.

Here I have checked one if condition. When the if condition is true, textview(tvHeader) which defined in the MyViewHolderHeader class will get the value.

When the if condition is false, textview(tvchild) which defined in the MyViewHolderChild class will get the value.