epoxy icon indicating copy to clipboard operation
epoxy copied to clipboard

Item jumps during disappear animation when using setItemSpacingDp

Open denis-bezrukov opened this issue 4 years ago • 4 comments

We use setItemSpacingDp for some grids in our app. When items removed, they jump like if there is no spacing added for them

How it looks:

ezgif-4-3931abe96f16

it's reproducible with minimal changes on epoxy-sample. Here is a link to the branch with these changes.

Steps:

  1. install the sample from the branch
  2. add some items
  3. tap clear button

Actual result: items being removed jump to top before disappear animation. Expected result: items do not jump

I didn't investigate it a lot, but probably in this case recycler returns NO_POSITION for the removing view, so decorator doesnt' modify the bounds:

    int position = parent.getChildAdapterPosition(view);
    if (position == RecyclerView.NO_POSITION) {
      // View is not shown
      return;
    }

Is there any workaround for this? Thanks in advance!

denis-bezrukov avatar Nov 14 '20 20:11 denis-bezrukov

Thanks for the clear report. I don't know any workaround off the top of my head, and we don't internally use this decorator, so this won't be a high priority fix for us, but I'm happy to approve any change you want to make.

I just took a brief look to see if I could find any workarounds - one hacky possibility is to keep a weak reference to each view and store the last spacing applied to it, then if the view doesn't have an adapter position used the last spacing we gave it instead as a fallback

elihart avatar Nov 16 '20 22:11 elihart

yeah, I was thinking about something similar, but instead of weak ref per view I've used android's View.setTag/View.getTag for keeping last known offsets.

denis-bezrukov avatar Nov 17 '20 17:11 denis-bezrukov

Good idea, that seems like a better solution

elihart avatar Nov 17 '20 20:11 elihart

You can get the old position from viewHolder object:

var posInAll = recyclerView.getChildAdapterPosition(item) if (posInAll == RecyclerView.NO_POSITION) { posInAll = recyclerView.getChildViewHolder(itemView).oldPosition }

LiGuo802 avatar Jun 14 '22 08:06 LiGuo802