RecyclerView Adapter notifyDataSetChanged stops fancy animation
No, it is wrong. First of all, you cannot reference to the position passed to the onBindViewHolder after that method returns. RecyclerView will not rebind a view when its position changes (due to items moving etc).
Instead, you can use ViewHolder#getPosition()
which will return you the updated position.
If you fix that, your move code should work & provide nice animations.
Calling notifyDataSetChanged
will prevent predictive animations so avoid it as long as you can. See documentation for details.
Edit (from comment): to get position from the outside, get child view holder from recyclerview and then get position from the vh. See RecyclerView api for details
1) You'll use notifyItemInserted(position);
or notifyItemRemoved(position);
instead of notifyDataSetChanged()
for animation.
2) You can just manually fix your problem - using
public void move(int from, int to){
Track track = mArray.remove(from);
mArray.add(to, track);
notifyItemMoved(from, to);
ViewHolder fromHolder = (ViewHolder) mRecyclerView.findViewHolderForPosition(from);
ViewHolder toHolder = (ViewHolder) mRecyclerView.findViewHolderForPosition(to);
Tag fromTag = fromHolder.itemView.getTag();
fromHolder.itemView.setTag(toHolder.itemView.getTag());
toHolder.itemView.setTag(fromTag);
}
There is a way to preserve fancy animations with just notifyDataSetChanged()
You need to make your own
GridLayoutManager
with overridensupportsPredictiveItemAnimations()
method returningtrue
;You need to
mAdapter.setHasStableIds(true)
The part I find tricky is you need to override you adapter's
getItemId()
method. It should return value that is truly unique and not a direct function ofposition
. Something likemItems.get(position).hashCode()
Worked perfectly fine in my case - beautiful animations for adding, removing and moving items only using notifyDataSetChanged()