Search code examples
androidandroid-recyclerviewitem-decoration

recycler view item decoration, getItemOffsets is only called on the last added item


I have an item decoration attached to my recycler view. It should add a large amount of padding on only the last item. This works fine. However, as I add new items, getItemOffsets is called only for the last item (and not to every item in the recycler view`). This way, I end up with this large padding on every item.

How could I remove the right padding on the rest of the views when a new view is added? I want to add items the correct way to preserve animations

public void onItemInserted(Card card, int position){
    cardList.add(card);
    notifyItemInserted(getItemCount() -1);
}

My item offsets method:

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
    super.getItemOffsets(outRect, view, parent, state);
    outRect.top = horizontalSpace;
    outRect.bottom = horizontalSpace;
    outRect.left = horizontalSpace;
    outRect.right = 0;

    if (parent.getChildAdapterPosition(view) == parent.getChildCount() - 1){
       outRect.right = endSpace;
    }
}

Solution

  • getItemOffsets() is called for the last item only. So, decoration for old items won't ever be re-stored. This happens because you invoked: notifyItemInserted(getItemCount() -1);

    In order to call the getItemOffsets() for the last two items, you must:

    public void onItemInserted(){
        items++;
        int lastPosition = getItemCount() - 1;
        if(lastPosition > 0) {
            // Request to redraw last two items. So, new item will receive proper padding and old item will restore to the default position
            notifyItemRangeChanged(lastPosition - 1, lastPosition);
        } else {
            notifyItemChanged(lastPosition);
        }
    }
    

    Also, as yourself mentioned, you should use state.getItemCount() instead of parent.getChildAdapterPosition(view) during getItemOffsets()