如何实现RecyclerView的ItemAnimator来禁用notifyItemChanged的动画

时间:2015-04-26 04:45:59

标签: android animation android-recyclerview

在我的项目中,我需要在RecyclerView时禁用notifyItemChanged的“更改”动画。

我在RecyclerView的来源进行了调查,并覆盖了android.support.v7.widget.DefaultItemAnimator,如下所示:

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;
    }
}

但我不确定我是否符合Google文档的规范: RecyclerView.ItemAnimator.animateChange

根据我的理解源代码,如果我没有正确覆盖该方法,则oldHolder 将不会被回收。

请帮我弄清楚如何以正确的方式覆盖animateChange

9 个答案:

答案 0 :(得分:101)

我找到了正确的解决方案,只需删除animateChange。

这非常简单。 Google已实施该功能。

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

文档:setSupportsChangeAnimations

答案 1 :(得分:47)

我遇到了同样的问题。当调用notifyItemChanged时,有一个红色覆盖闪烁。在试验你的代码之后,我终于通过简单地调用

删除了默认的Animator
recyclerView.setItemAnimator(null);

在RecyclerView上。

答案 2 :(得分:8)

由于google删除方法setSupportsChangeAnimations()(但为什么?)在支持库23.1.0中,因此@Kenny的答案不再有效。

在某些情况下,setChangeDuration(0)可以作为解决方法。

@edit 我建议使用类似的东西:

  RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
        if (animator instanceof SimpleItemAnimator) {
            ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
        }

答案 3 :(得分:4)

如果找到了解决方案,那么每个想要保留DefaultItemAnimator给出的所有动画的人,除去每次更新视图时出现的“闪烁”动画。

首先,获取DefaultItemAnimator的源代码。在项目中创建一个具有相同名称的类。

其次,将ItemAnimator设置为修改后的DefaultItemAnimator的新实例,如下所示:

recyclerView.setItemAnimator(new MyItemAnimator());

然后,进入新类源代码并找到方法

animateChangeImpl(final ChangeInfo changeInfo) { ... }

现在,我们只需要找到更改alpha值的方法调用。找到以下两行并删除.alpha(0)和.alpha(1)

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

喜欢这样

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

答案 4 :(得分:3)

如果有人像我一样绊倒:
 不知怎的[(x,y)| x <-[68..70], y <- bmiTell x 185] 对我不起作用,但setSupportsChangeAnimations(false)刚刚删除了动画。

答案 5 :(得分:1)

最简单的解决方案是在构造函数中扩展node<T>& list并将DefaultItemAnimator设置为setSupportsChangeAnimations

false

答案 6 :(得分:1)

我创建了一个扩展类,以禁用动画

import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SimpleItemAnimator

fun RecyclerView.disableAnimation() {
    (itemAnimator as? SimpleItemAnimator)?.supportsChangeAnimations = false
}

您可以这样称呼它:

recyclerView.disableAnimation()

答案 7 :(得分:0)

这是一个简单而有效的方法:

public class NoAnimAnimator extends DefaultItemAnimator {
    public NoAnimAnimator() {
        setSupportsChangeAnimations(false);
        setChangeDuration(0);
    }
}

并在您的回收站视图中添加动画师:

recylerview.setItemAnimator(new NoAnimAnimator());

快乐编码!

答案 8 :(得分:-1)

以上解决方案均不适合我。有效的方法是使用 TransitionManager ,并将场景过渡设置为null

TransitionManager.go(new Scene(recyclerView), null);

重新启用默认动画,您可以创建一个新的自动过渡并将其设置为与上述相同的方法:

AutoTransition autoTransition = new AutoTransition();
TransitionManager.go(new Scene(recyclerView), autoTransition);