How to implement ItemAnimator of RecyclerView to d

2020-02-07 17:20发布

In my project I need disable the "change" animation of RecyclerView while notifyItemChanged.

I investigated in the source of RecyclerView and had overridden android.support.v7.widget.DefaultItemAnimator as below:

private static  class ItemAnimator extends DefaultItemAnimator
{
    @Override
    public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
        if(oldHolder != null)
        {
            oldHolder.itemView.setVisibility(View.INVISIBLE);
            dispatchChangeFinished(oldHolder, true);
        }

        if(newHolder != null)
        {
            dispatchChangeFinished(newHolder, false);
        }

        return false;
    }
}

But I am not sure if I match the spec of the Google document: RecyclerView.ItemAnimator.animateChange

According to my understanding source code, if I do not override the method properly, the oldHolder will not be recycled.

Please help me figure out how to override animateChange in a correct way.

8条回答
唯我独甜
2楼-- · 2020-02-07 17:45

I have found the correct solution to just remove the animateChange.

It's very simple. Google has implemented the functionality.

((SimpleItemAnimator) RecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

Documentation: setSupportsChangeAnimations

查看更多
3楼-- · 2020-02-07 17:45

Just if someone stumbles like me:
Somehow setSupportsChangeAnimations(false) didn't work for me, but recyclerView.getItemAnimator().setChangeDuration(0) has just removed the animation nicely.

查看更多
我命由我不由天
4楼-- · 2020-02-07 17:48

I had the same problem. When calling notifyItemChanged there was a red overlay flashing. After experimenting around with your code I finally removed the default Animator by simply calling

recyclerView.setItemAnimator(null);

on the RecyclerView.

查看更多
我只想做你的唯一
5楼-- · 2020-02-07 17:55

@Kenny answer didn't work anymore because google remove method setSupportsChangeAnimations() (but why?) in support library 23.1.0.

In some case setChangeDuration(0) can work as workaround.

@edit I suggest use something like that:

  RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
        if (animator instanceof SimpleItemAnimator) {
            ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
        }
查看更多
三岁会撩人
6楼-- · 2020-02-07 17:55

If found a solution, for everyone who wants to keep all the animations given by the DefaultItemAnimator, but getting rid of the "blink" animation that occurs every time the view is updated.

First, get the source code of DefaultItemAnimator. Create a class with the same name in your project.

Second, set the ItemAnimator to a new instance of your modified DefaultItemAnimator, like so:

recyclerView.setItemAnimator(new MyItemAnimator());

Then, go in the new classes source code and locate the method

animateChangeImpl(final ChangeInfo changeInfo) { ... }

Now, we simply have to locate the method calls changing alpha values. Find the following two lines and remove the .alpha(0) and .alpha(1)

oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { ... }
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).alpha(1).setListener(new VpaListenerAdapter() { ... }

like so

oldViewAnim.setListener(new VpaListenerAdapter() { ... }
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).setListener(new VpaListenerAdapter() { ... }
查看更多
Bombasti
7楼-- · 2020-02-07 17:58

The easiest solution is to extend DefaultItemAnimator and set setSupportsChangeAnimations to false right in the constructor:

public class DefaultItemAnimatorNoChange extends DefaultItemAnimator {
    public DefaultItemAnimatorNoChange() {
        setSupportsChangeAnimations(false);
    }
}
查看更多
登录 后发表回答