Multiple Layout(viewHolder) in RecyclerView

Multiple Layout(viewHolder) in RecyclerView

 
  • when we need to set layout based on condition or different layout for multiple items than we need to create multiple viewHolder that can create different layout for each different items.
 
  1. we will create one based or common class that inherits all type of different viewHolder class.
      • reason for doing this is polymorphism
      • Recycler view adapter class can only need one type of viewHolder and cannot extend multiple type of it
      • so we will create one parent type and all other type will inherits this parent type.
  1. Now , make this parent class sealed class and store all the different layout viewholder in this.
  1. all child layout viewHolder class will have bind() method but with different parameter and different implementation based on data it need and how this data will be set on view or layout.
  1. inside Adapter class we need to override getItemViewType(position: Int): Int {...} method.
      • this method will return int value means it can return refence of different layout based on position.
  1. this refence can be get in onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {...} method as parameter to create layout view based on this type and return inside its appropriate child viewHolder object that extends BaseViewHolder class.
      • because BaseViewHolder() is parent class , so here polymorphism occur and instance of base class will be initialized with its child class object to behave like it.
  1. So we will get different layout viewHolder object as holder and position inside onBindViewHolder(holder: HomeViewHolder, position: Int) method so we can call its bind method for each item with different implementation of it based on position , viewHolder , bind method implementation and layout.
 

Example:

  • In this Example We have used viewBinding instead of using View
package com.example.pdavenuetask.adapters import android.content.Context import android.graphics.Color import android.util.Log import android.view.View import android.view.animation.AnimationUtils import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import com.bumptech.glide.Glide import com.example.pdavenuetask.R import com.example.pdavenuetask.databinding.HomeDataListItem2Binding import com.example.pdavenuetask.databinding.HomeDataListItemBinding import com.example.pdavenuetask.models.HomeData sealed class HomeViewHolder(binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) { class ListViewHolder(private val binding: HomeDataListItemBinding) : HomeViewHolder(binding) { fun bind(context: Context, model: HomeData) { val animation = AnimationUtils.loadAnimation(context, R.anim.slide_down) binding.root.startAnimation(animation) if (model.jsonImage.endsWith(".json")) { binding.animationView.visibility = View.VISIBLE binding.animationView.setAnimationFromUrl(model.jsonImage) } else { binding.animationView.visibility = View.GONE binding.imageView.setBackgroundColor(Color.parseColor(model.bgColor)) Glide.with(context).load(model.jsonImage).into(binding.imageView) } } } class GridViewHolder(private val binding: HomeDataListItem2Binding) : HomeViewHolder(binding) { fun bind(context: Context, model: HomeData) { binding.recyclerView.layoutManager = GridLayoutManager(context, model.columnCount?.toIntOrNull() ?: model.data.size) Log.d("=-=-=-", "bind: ${model}") val adptr = SubRecAdapter(context, model) binding.recyclerView.adapter = adptr binding.recyclerView.itemAnimator = DefaultItemAnimator() } } }
 

Adapter class

package com.example.pdavenuetask.adapters import android.content.Context import android.util.Log import android.view.LayoutInflater import android.view.ViewGroup import android.view.animation.AnimationUtils import androidx.recyclerview.widget.RecyclerView import com.example.pdavenuetask.R import com.example.pdavenuetask.databinding.HomeDataListItem2Binding import com.example.pdavenuetask.databinding.HomeDataListItemBinding import com.example.pdavenuetask.models.HomeData class MyRecAdapter(val context: Context, val homeDataList: ArrayList<HomeData>) : RecyclerView.Adapter<HomeViewHolder>() { override fun getItemViewType(position: Int): Int { return when (homeDataList[position].type) { "singlerow" -> R.layout.home_data_list_item "topgrid" -> R.layout.home_data_list_item2 "fourgrid" -> R.layout.home_data_list_item2 "Quicktask" -> R.layout.home_data_list_item2 else -> 0 } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeViewHolder { return when (viewType) { R.layout.home_data_list_item -> HomeViewHolder.ListViewHolder( HomeDataListItemBinding.inflate( LayoutInflater.from(context), parent, false ) ) R.layout.home_data_list_item2 -> HomeViewHolder.GridViewHolder( HomeDataListItem2Binding.inflate( LayoutInflater.from(context), parent, false ) ) else -> { throw IllegalArgumentException("Invalid View Type Provided") } } } override fun getItemCount(): Int = homeDataList.size override fun onBindViewHolder(holder: HomeViewHolder, position: Int) { val model = homeDataList[position] Log.e("=+=+", "$position") Log.e("=+=+", "$model") when (holder) { is HomeViewHolder.ListViewHolder -> holder.bind(context, model) is HomeViewHolder.GridViewHolder -> holder.bind(context, model) } } }