I'm trying to have a space at the end of the last item in a RecyclerView.
For this I am using a ItemDecoration, but when adding a new item, both the previos item, and the new item will have the Bottom Offset. If I add a 3rd Item, the first item will no longer have offset, but the 2nd and newly added 3rd will have.
Below is my ItemDecoration class
class BottomOffsetDecoration : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
//dimension of offset
val bottomOffset = view.context.resources.getDimension(R.dimen.player_list_offset).toInt()
val dataSize = state.itemCount
val position = parent.getChildAdapterPosition(view)
//Logic of showing space or not
if (dataSize > 0 && position == dataSize - 1) {
outRect.set(0, 0, 0, bottomOffset)
} else {
outRect.setEmpty()
}
}
}
This gets added to my Recyclerview with Databinding like this:
@BindingAdapter(value = ["adapterListener", "itemList"])
fun RecyclerView.bindList(adapterListener: PlayerListItemListener, itemList: List<PlayerListItem>) {
var adapter = this.adapter
//copy the list as DiffUtils will ignore it if it is the same list every call
val listCopy = ArrayList(itemList)
if (adapter == null) {
adapter = PlayerListAdapter(adapterListener)
this.apply {
setAdapter(adapter)
//DECORATION
addItemDecoration(BottomOffsetDecoration())
setHasFixedSize(true)
}
}
(adapter as PlayerListAdapter).submitList(listCopy)
}
As for Recylerview Adapter I am using the ListAdapter with DiffUtils, not the RecyclerView.Adapter
Question is: how do I remove the offset from the last item once a new Item is added?
DISCLAIMER: I can not use the below for my case:
android:paddingBottom="50dp"
android:clipToPadding="false"
Thank you in advance!
So, for anyone else coming across this problem, here is how I solved it.
You need to call invalidateItemDecorations() after ListAdapter applied the changes to the list.
In my case I used submitList(list, commitCallback)
, like below inside my BindingAdapter method:
(adapter as PlayerListAdapter).submitList(listCopy) {
post {
//remove decoration from other elements so the bottom offset is added to only the last element inserted
invalidateItemDecorations()
}
}
I also updated my getItemOffset()
, this was not part of the problem, but I like this code more:
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
val bottomOffset = view.context.resources.getDimension(R.dimen.player_list_offset).toInt()
val adapter = parent.adapter
if (adapter == null || adapter.itemCount == 0) {
return
}
if (parent.getChildAdapterPosition(view) == adapter.itemCount - 1) {
outRect.bottom = bottomOffset
} else {
outRect.bottom = 0
}
}
Happy coding!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.