Search code examples
androidkotlinandroid-recyclerviewandroid-adapteritem-decoration

Prevent ItemDecorator to add dividers to my viewtypes


I have made a recyclerview with ConcatAdapter, the idea is that each of these adapters has 2 viewtypes, one for the header and one for the items, now , when applying a divider with itemDecorator on all of these adapters its applied to each viewtype, but I dont want to apply the decorator to all viewtypes but instead after the content viewtype

 //Merge all together
        val concatAdapter = ConcatAdapter(
            firstConcatAdapter,
            secondConcatAdapter,
            thirdConcatAdapter
        )

        val dividerItemDecorationInstance =
            DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
        test_rv.addItemDecoration(dividerItemDecorationInstance)
        dividerItemDecorationInstance.setDrawable(
            ContextCompat.getDrawable(
                requireContext(),
                R.drawable.recycler_home_divider
            )!!
        )
        test_rv.layoutManager = LinearLayoutManager(requireContext())
        test_rv.adapter = concatAdapter

So here test_rv is one recyclerview, and I inflate different adapters inside this recyclerview in which I show different custom parts of UI , each of these adapters, firstConcatAdapter and so on has 2 viewtypes, it has a header and then the items, but my output is this

enter image description here

So whats happening here is that the divider is also applying to the header viewtype , and I dont want it to be displayed there, I only need the dividers after all the view has been inflate with its viewtypes


Solution

  • You can extend ItemDecoration and make your logic to show the divider respected to item type , lets say you have item type as (header or item)

    import android.graphics.Canvas
    import android.graphics.Paint
    import androidx.recyclerview.widget.RecyclerView
    
    
    class HorizontalItemDecoration(
    color: Int,
    private val heightInPixels: Int) : RecyclerView.ItemDecoration() {
    
    private val paint = Paint()
    
     init {
      paint.color = color
      paint.isAntiAlias = true
     }
    
    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
    super.onDraw(c, parent, state)
    
    val left = parent.paddingLeft
    val right = parent.width - parent.paddingRight
    
    val childCount = parent.childCount
    for (i in 0 until childCount) {
      val child = parent.getChildAt(i)
    
      val params = child.layoutParams as RecyclerView.LayoutParams
    
      val top = child.bottom + params.bottomMargin
      val bottom = top + heightInPixels
      val adapterPosition = parent.getChildAdapterPosition(child)
      val viewType= parent.adapter.getItemViewType(adapterPosition )
      if (viewType == RowType.ITEM.ordinal) { // here you make check before drawing the divider where row type determine if this item is header or normal item
        c.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), paint)
       }
      }
     }
    }
    

    row type enum

    enum class RowType {
    ITEM,
    HEADER;
    }
    

    to use ItemDecoration

    val dividerHeightInPixels = resources.getDimensionPixelSize(R.dimen.1sdp)
    val dividerItemDecoration = HorizontalItemDecoration(ContextCompat.getColor(requireContext(), R.color.divider_color), dividerHeightInPixels)
    recyclerView.addItemDecoration(dividerItemDecoration)