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
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.