I have different types of items being rendered in a RecyclerView
using a GridLayoutManager
with dynamic column number. The problem is, I have an RecyclerView.ItemDecoration
which is to be applied for let's say Type A
items only. this RecyclerView.ItemDecoration
adds margin to the left/start to those items on the left hand side column, and margin to the right/end to those items on the right hand side column. It's basically to make the items look a bit more centered and so so stretched (this is used on a tablet/landscape mode). The RecyclerView
grid looks something like this:
| A | | A |
| A | | A |
| B |
| A | | A |
| A | | A |
| B |
| A | | A |
The ItemDecoration
looks like this:
class TabletGridSpaceItemDecoration(private val space: Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) = with(outRect) {
val isTypeAItemLayout = view.findViewById<ConstraintLayout>(R.id.type_a_item_container) != null
if (isTypeAItemLayout) {
val adapterPosition = parent.getChildAdapterPosition(view)
if (adapterPosition % 2 == 0) {
left = space
right = 0
} else {
left = 0
right = space
}
}
}
}
The problem with this decorator is that after the first type B
item on the list, the indexes get screwed for the next type A
items. So first item after B
according to the example provided will have adapterPosition == 5
, so according to TabletGridSpaceItemDecoration
the marging should be added to the right, which is incorrect.
I tried having a
HashMap
to keep theadapterPosition
and the real position of the item, i.e. the position it would have on the adapter ignoring nontype A
items. This has some other problems I won't get too much into details, but it's doesn't feel the correct way to do it.Another thing I tried is to check the location on the screen of the view (more to the left or to the right) the item decoration is going to be applied. The problem with this is that the view has not been rendered yet when this decorator is ran. Adding a
ViewTreeObserver.OnGlobalLayoutListener
on the view is worthless since by the time the view is rendered the item decoration is already applied, which makes no effect on the view.
What I would like to do is to check whether or not an item is in "column 0" or "column 1" and add margin accordingly.
I don't know how is this possible and didn't find the way to do it looking at what the GridLayoutManager
provides, that can be accessed by parent.layoutManager as GridLayoutManager
.
Any ideas? Thanks
LayoutParams
. Works like a charm, thank you! – Lineberry