Android

How to Create Sectioned RecyclerView in Android

I this tutorial we will learn how to create sectionedrecyclerview in android. Each section will contain a header and the list of items that belong to that section. It will help us to categorize items in recyclerview that leads to better understanding of UI.

Example

Let’s assume we want to show a list of products. Each product belongs to a category. And we want to categorize that products list on base of that category. For this we will use Sectioned Recyclerview. This recyclerview will categorize the products and will create sections for each category. Each product will remain under the section of its category.

Our output will be like this.

Output
Sectioned RecyclerView Android

Let’s see how to achieve this.

First create a new android project and name it as SectionedRecyclerView. After creating new project now open the build.gradle file and add this dependency in dependencies section.

Add Dependency
implementation 'com.github.francescopedronomnys:Sectioned-RecyclerView:0.2.2-mod'

Next add this line in settings.gradle file in repositories block under DependencyResolutionManagement section .

maven { url 'https://jitpack.io' }

Now sync the project.

After successfully synchronization now we are able to use this library classes in our project to make a sectioned recyclerview. This library will make it easy to create sections in recyclerview.

Model Class

Now create a model class named as Product.

class Product(var id: Int = 0, val name: String,val category: String) {
}

We have created a class with three member variable, id, name and category.

Next add recyclerivew in main activity.

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

  <androidx.recyclerview.widget.RecyclerView
      android:layout_width="match_parent"
      android:id="@+id/recycler_view"
      android:layout_height="match_parent"/>
</LinearLayout>
RecyclerView Layout Files

We have to create two layout files for recyclervew. One is for the product item. And second is for the header.

layout_single_product.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:textColor="#000"
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp" />
</LinearLayout>
layout_sub_header.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#F3F1F1"
    android:layout_height="wrap_content">

        <TextView
            android:textColor="#F30A0A"
            android:padding="16dp"
            android:textStyle="bold"
            android:gravity="center"
            android:id="@+id/tv_header"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
</LinearLayout>
Sectioned RecyclerView Adapter

Now create an adapter for Sectioned RecyclerView

class ProductsListAdapter(val context: Context, val products: List<Product>) :
    SectionedRecyclerAdapter<ProductsListAdapter.SectionHeaderHolder, ProductsListAdapter.ProductsListHolder>() {
    class ProductsListHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val textView = itemView.findViewById<TextView>(R.id.tv_name)
    }

    class SectionHeaderHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val textView = itemView.findViewById<TextView>(R.id.tv_header)
    }

    override fun onPlaceSubheaderBetweenItems(itemPosition: Int, nextItemPosition: Int): Boolean {
        return !products.get(itemPosition).category.equals(products.get(nextItemPosition).category)
    }

    override fun onCreateSubheaderViewHolder(
        parent: ViewGroup?,
        viewType: Int
    ): SectionHeaderHolder {
        val view = LayoutInflater.from(context).inflate(R.layout.layout_sub_header, parent, false)
        return SectionHeaderHolder(view)
    }

    override fun onCreateItemViewHolder(parent: ViewGroup?, viewType: Int): ProductsListHolder {
        val view =
            LayoutInflater.from(context).inflate(R.layout.layout_single_product, parent, false)
        return ProductsListHolder(view)
    }

    override fun onBindSubheaderViewHolder(p0: SectionHeaderHolder?, p1: Int) {
        val product = products.get(p1)
        p0!!.textView.text = product.category
    }

    override fun onBindItemViewHolder(p0: ProductsListHolder?, p1: Int) {
        val product = products.get(p1)
        p0!!.textView.text = product.name
    }

    override fun getCount(): Int {
        return products.size
    }
}

Above we have created an adapter for Sectioned RecyclerView. This adapter contains two holder classes. One for the Product Item and second for Section Header. Similarly there are two onCreate methods and two onBind methods. And there is an extra method onPlaceSubheaderBetweenItems  . This method will notify the adapter that when to create new header in recyclerview.

MainActivity
class MainActivity : AppCompatActivity() {
    val context = this@MainActivity
    var products = ArrayList<Product>()
    lateinit var recyclerView: RecyclerView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initViews()
    }

    fun initViews() {

        initRecyclerView()
        initProductsList()
        setRecyclerViewAdapter()
    }

    fun initRecyclerView() {
        recyclerView = findViewById(R.id.recycler_view)
        val layoutManager = LinearLayoutManager(context)
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = layoutManager
    }

    fun initProductsList() {
        for (i in 1..4) {
            products.add(Product(i, "Product $i", "Fashion"))
        }
        for (i in 5..8) {
            products.add(Product(i, "Product $i", "Beauty"))
        }
        for (i in 9..12) {
            products.add(Product(i, "Product $i", "Electronics"))
        }
    }

    fun setRecyclerViewAdapter() {
        products.sortBy { it.category }
        val adapter = ProductsListAdapter(context, products)
        recyclerView.adapter = adapter
    }
}

This is our main activity. Here we set layout manager of recyclerview and create a list of products and set adapter of recycler view.

Leave a Reply

Your email address will not be published. Required fields are marked *