Home > database >  Android recyclerview with view type
Android recyclerview with view type

Time:12-13

I am trying to inflate two views in recyclerview where the condition is like "I have two views lets say view1 and view2 now while iterating over arraylist which is passed to the recycler adapter I want to check 'year' key in each object, if value of a key is new or different value than the previous object then I want to inflate the view1 which will be like header for next rows and at the same time I want to print that object where we found the new value for 'year' as a row" I am trying it with the getItemViewType() method but not able to achieve it.

I am trying it with the getItemViewType() method but not able to achieve it.

CodePudding user response:

You need to override this function to receive the correct view type

override fun getItemViewType(position: Int): Int {
    if(getItem(position) is Header) return 0 else return 1   
}

than in your getItemViewType() will have the correct integer that represents your view type.

CodePudding user response:

I'll assume that you are using Kotlin. First you must define a BaseItem interface. Your Item should extends this base interface. Then you group your items by year and add an extra item Header. This Header also extends the base interface above.

BaseItem.kt

interface BaseItem

Item.kt

data class Item(val year:Int,val name:String) : BaseItem

Header.kt

data class Header(val year:Int) : BaseItem

HeaderViewHolder.kt

class HeaderViewHolder(view:View):RecyclerView.ViewHolder(view){
  fun bindView(item:BaseItem){
    if(item !is Header) return
    ... // Do something
  }
}

ItemViewHolder.kt

class ItemViewHolder(view:View):RecyclerView.ViewHolder(view){
  fun bindView(item:BaseItem){
    if(item !is Item) return
    ... // Do something
  }
}

For the Adapter, I recommended you use ListAdapter.

class MyAdapter : ListAdapter<BaseItem,RecyclerView.ViewHolder>(ITEM_CALLBACK){
companion object {
    private val ITEM_CALLBACK = object : DiffUtil.ItemCallback<String>() {
      override fun areItemsTheSame(oldItem: String, newItem: String): Boolean {
        if(oldItem is Header && newItem is Header) return oldItem.year==newItem.year
        else if(oldItem is Item && newItem is Item) return oldItem.name == newItem.name
        return false
      }

      override fun areContentsTheSame(oldItem: String, newItem: String): Boolean {
        if(oldItem is Header && newItem is Header) return oldItem==newItem
        else if(oldItem is Item && newItem is Item) return oldItem == newItem
        return false
      }
    }
  }

  override fun getItemViewType(position: Int): Int {
    if(getItem(position) is Header) return 0 
    return 1
  }

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder{
    if(viewType==0){
      val view = ... // Inflate your header view
      return HeaderViewHolder(view)
    }
    val view = ... // Inflate your item view
    return ItemViewHolder(view)
  }

  override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    if(holder is HeaderViewHolder) holder.bindView(getItem(position))
    else if(holder is ItemViewHolder) holder.bindView(getItem(position))
  }
}

And in your activity, group your items and add them to a new list. Then submit the list to your adapter.

override fun onCreate(savedInstanceState:Bundle){
    super.onCreate(savedInstanceState)
...

    val old:List<Item> = listOf(...) // This is your original list of items

    val groupMap = oldItems.groupBy{ it.year } // Group them by year

    val newItems = mutableListOf<BaseItem>() // New list of base items

    // Loop through the map and add an extra Header item to the new list
    groupMap.forEach{ k,v->
        newItems.add(Header(k))
        newItems.addAll(v)
    }

    adapter.submitList(newItems)

...
}
  • Related