0

I have a basic RecyclerView setup on a chat-like app and I have hit an issue with the item animations.

The project is making use of Room with Paging 3 and DiffUtils for the RecyclerView adapter, so this is all automated, but the core of the problem can be simplified to this:

  1. When I send a new message, that message is added to the RecyclerView
    • here the adapter is triggering notifyItemInserted or notifyItemRangeInserted which causes the entire message list to shift up softly and the new message fades in after
  2. I scroll the list to the bottom so the new added item becomes visible
  3. When I receive a read status from the server I update the status of that message
    • here the adapter is triggering notifyItemChanged or notifyItemRangeChanged which has no default animations on its own, it just updates the item with the new information

All of this is working well on its own, but the problem is when I receive a status update from the server faster than the insert animation has a chance to finish. When that happens the notifyItemChanged or notifyItemRangeChanged kicks in and skips the animation initiated by notifyItemInserted or notifyItemRangeInserted. The list till shifts upwards, but the fade in no longer happens, instead the item is instantly made visible all the while the list is still shifting up, overlaying the item previously occupying that last position causing an ugly visual experience.

I can kinda "cheat" by delaying the step in 2. to engage after the animation is supposedly over, but then it introduces another visual issue if the user sends multiple messages quickly or receives them in the same fashion or in certain cases it just does not show any animation because the new item is loaded outside of the list and only scrolled after the animation time is elapsed, so this is not a solution.

first second
enter image description here enter image description here

In this example there are 2 recyclerviews set up with the same adapter slightly changed to make it easier to compare the issue in the same action.

The left recyclerview is not doing any update when an item is inserted, but it is the behavior I expect to display even if I update the item during the item insertion animation. On the right recyclerview is the actual problem, as you can see new items are showing in full over the old ones before they have a chance to move out of the way. The first example recording has scroll to bottom with no delay after the item is inserted, the second example has a delay that matches the insertion animation duration.

Reminder: this is just a manual example, the real application in my case is being done automatically via the integration I mentioned above, I am not the one in control of when the notifyItem* calls are made at any point.

How can I make sure the insert animation does not get interrupted even if I am updating the item data in the middle of the animation?

EDIT: I already searched for a solution in the questions posted before, but none are related to this one nor do the similar ones provide a solution to my problem.

Shadow
  • 4,168
  • 5
  • 41
  • 72
  • Does this answer your question? [Override animation for notifyItemChanged in RecyclerView.Adapter](https://stackoverflow.com/questions/31897469/override-animation-for-notifyitemchanged-in-recyclerview-adapter) – Uuu Uuu Jan 21 '21 at 04:19
  • @UuuUuu I already saw that one, but it is not the problem that I have. That user was not using the correct method for updating items in a recyclerview, which is why they were all behaving as if they were being inserted brand new, even though they were suppose to be updated only. Mine is inherent animation deeply nested to a point where I cannot simply override, there's at least 10 points in the `DefaultItemAnimator` that switch the alpha to 1, many of which are inside private methods, including the ones that are responsible for the `notifyItemChanged` calls. – Shadow Jan 21 '21 at 04:32

0 Answers0