I am using a RecyclerView
fed with data from a SortedList
using a SortedListAdapterCallback
. I want to disable animations for onChange
events, but preserve them for onInserted
/onRemoved
/onMoved
. I have tried calling setSupportsChangeAnimations(false)
on the DefaultItemAnimator
used by the RecyclerView
, but the animation still appears. If I call setItemAnimator(null)
all animations are successfully removed as expected though.
I tried looking at the implementation and it seems like if supportsChangeAnimations
is true
, the RecyclerView
will animate change events by keeping the old viewHolder and cross-fade it to the new viewHolder. I don't want that. If supportsChangeAnimations
is false
, the old and new viewHolders will however be the same object, and there will instead be an onMoved
animation from x to x (i.e., no actual move). This however means that the item will get an annoying bounce effect. I don't want that either, I want no animation at all. :(
From DefaultItemAnimator.java:
@Override
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) {
if (oldHolder == newHolder) {
// Don't know how to run change animations when the same view holder is re-used.
// run a move animation to handle position changes.
return animateMove(oldHolder, fromX, fromY, toX, toY);
}
...
Sometimes when I load my list I asynchronously fetch some data and update items 1-3 times, and it looks really crappy when it bounces and flickers every time.
How do I effectively completely disable onChange
animations without resorting to writing a completely custom ItemAnimator?
The above solution does not work for me with support library version of 25.3.1 as I want to disable all recycler view items' animation. I solved it by overriding
SimpleItemAnimator
:Looking through the code (I'm using support library 25.2.0):
setSupportsChangeAnimations(<value>)
is a method on the abstract classSimpleItemAnimator
, which is alsoDefaultItemAnimator
's superclass. Internally, it modifies the value ofmSupportsChangeAnimations
.Performing a text search in
DefaultItemAnimator
's code, reveals that neithermSupportsChangeAnimations
, norgetSupportsChangeAnimations()
are queried --> theDefaultItemAnimator
literally ignores this flag.The correct solution is to extend the
DefaultItemAnimator
in the following manner:See docs
animateChange(...)
to understand why it was needed to calldispatchChangeFinished(...)
when no animations were run.Probably there's a more elegant way to write the else branch when there are no animations to be run, but alas, this achieves the desired behavior.
Kind'of late, but hope this helps!