0

Im trying to delete the empty column Item decoration as per the below Image. I Initially thought to restrict the spancount for the last row as per the content using below code in comments but however Im not successful.

below is the code and Image as a result.

enter image description here

 val taskDatesView: RecyclerView = binding.taskDatesRecyclerView
    val manager = GridLayoutManager(context,10)
    taskDatesView.layoutManager = manager
    taskDatesView.adapter = taskDatesAdapter

    createTasksViewModel.taskDates.observe(viewLifecycleOwner) {
        it?.let(taskDatesAdapter::setTaskDates)
        val decoration = DividerItemDecoration(context, HORIZONTAL)
        taskDatesView.addItemDecoration(decoration)
        /*manager.spanSizeLookup = object :SpanSizeLookup(){
            override fun getSpanSize(position: Int): Int {
                val lastRowCount = (taskDatesAdapter.itemCount%10)
                if(position>taskDatesAdapter.itemCount -lastRowCount){
                    return lastRowCount
                }
                return 10
            }
        }*/
        

when I uncommented the code and run the app below is the result

enter image description here

Any code references or links will be helpful. Thanks in Advance.

Manju
  • 720
  • 9
  • 23
  • 1
    I think that you will need a custom divider. See [this](https://stackoverflow.com/a/46216274/6287910) for some more info. – Cheticamp Jul 17 '22 at 14:26
  • Yes I tried the above solution too. Im getting only one column after adding custom item Divider. May be I need to dive in more in to internals of DividerItemDecoration. Im pretty much sure the UI looks most common use case they will be elegant solution to this. In search of that now. – Manju Jul 17 '22 at 14:44
  • 1
    `getSpanSize()` informs the layout manager about how many spans an item will consume and not the number of spans in a row. That is why the uncommented code is not working as you expect: You are tell the layout manager that each item (date) consumes 10 spans which is the entire width of the layout.. – Cheticamp Jul 17 '22 at 15:09
  • @Cheticamp yes I understood after tweaking the code with getSpansize(). However finally with the custom divider and changing the bottom of the divider based on the last row count, Im able to achieve what I want. updating the same as answer if anyone wants in future for ref. – Manju Jul 18 '22 at 10:12

1 Answers1

1

Within Custom Divider, modifying the bottom padding based on the lastRowCount it is working as expected.

Below is the working code and result also added comments within code for better understanding

fun drawHorizontal(c: Canvas?, parent: RecyclerView) {
    val noOfColumns = 10
    val top = parent.paddingTop
    var bottom = parent.height - parent.paddingBottom
    val childCount = parent.childCount
    // values required not to draw the bottom for last empty columns
    val lastRowCount = childCount % noOfColumns
    val numOfRows = childCount / noOfColumns
    for (i in 0 until childCount) {
        val child = parent.getChildAt(i)
        val params = child.layoutParams as RecyclerView.LayoutParams
        // this can be optimized to calculate only once for every row
        val rowNumber = ((i + 1) / noOfColumns) + 1
        // Within every row after crossing the lastRowCount the bottom should not be extended
        if ((i * rowNumber) - (lastRowCount - 1) > 0) {
            bottom = (child.height * (numOfRows))
        }
        val left = child.right + params.rightMargin + mDivider.intrinsicHeight
        val right = left + mDivider.intrinsicWidth
        mDivider.setBounds(left, top, right, bottom)
        mDivider.draw(c!!)
    }
}

enter image description here

If we need both vertical and horizontal orientations, use above and the below code

fun drawVertical(c: Canvas?, parent: RecyclerView){
    val dividerLeft = parent.paddingLeft
    val dividerRight = parent.width - parent.paddingRight
    val childCount = parent.childCount
    for (i in 0..childCount - 2) {
        val child: View = parent.getChildAt(i)
        val params = child.layoutParams as RecyclerView.LayoutParams
        val dividerTop: Int = child.getBottom() + params.bottomMargin
        val dividerBottom = dividerTop + mDivider.intrinsicHeight
        mDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom)
        mDivider.draw(c)
    }
}

enter image description here

Manju
  • 720
  • 9
  • 23