Java RecyclerView ItemAnimator';拆下';动画与';添加';动画

Java RecyclerView ItemAnimator';拆下';动画与';添加';动画,java,android,animation,android-recyclerview,Java,Android,Animation,Android Recyclerview,目前正在通过RecyclerView实现一个排序的“百科全书”,我可以排序、过滤、搜索等。在功能上,我的工作很好,所以我开始制作动画。我只想在数据集更改时使用动画,而不是滚动或触摸事件等,所以我只使用ItemAnimator 嗯,我的RecyclerView的许多排序、过滤或搜索方法实际上或实际上都会导致整个数据集被替换。我认为这些是最容易设置动画的情况,因为在这种情况下,我可以调用notifyDataSetRemoved(0,oldItemCount),然后调用notifydatasetine

目前正在通过RecyclerView实现一个排序的“百科全书”,我可以排序、过滤、搜索等。在功能上,我的工作很好,所以我开始制作动画。我只想在数据集更改时使用动画,而不是滚动或触摸事件等,所以我只使用ItemAnimator

嗯,我的RecyclerView的许多排序、过滤或搜索方法实际上或实际上都会导致整个数据集被替换。我认为这些是最容易设置动画的情况,因为在这种情况下,我可以调用
notifyDataSetRemoved(0,oldItemCount)
,然后调用
notifydatasetinestered(0,newItemCount)
,分别对每个修改的项目调用
animateRemove()
animateAdd()
。这就是发生的事情!我想,从一个非常简单的意义上说,它是有效的。但碰巧它只正常工作一次

以下是移除动画(当前):

和添加动画(当前):

下面是调用它的代码的示例:

public void filterDataSetExample() {
    int oldItemCount = getItemCount();

    // ... logic that changes the data set ...

    notifyItemRangeRemoved(0, oldItemCount);
    notifyItemRangeInserted(0, getItemCount());
}
第一次执行调用此序列的操作时,“移除”动画将平滑播放,然后是“添加”动画。当我第二次尝试时,问题就出现了

在第二次以及之后的任何时候,这两个动画都会以某种方式“合并”。基本上就是这样(每次都一样):

  • “删除”动画从“添加”动画中拾取延迟(基本+交错)。这意味着动画基本上是在同一时间播放的,这已经够糟糕的了

  • “添加”动画从“删除”动画中拾取alpha偏移,但仅适用于屏幕顶部75%左右的视图持有者。底部2-3仍然清晰可见。但总的来说,这意味着在我的整个列表中,70-80%的视图持有者是看不见的(因为它们被回收)。起初我以为它们不知怎么完全消失了,但如果我把alpha移位改成非0值,比如
    0.25f
    ,我可以看到那里的保持架,透明的

  • 最重要的是,如果我完全重新填充RecyclerView并简单地调用
    notifyDataSetChanged()
    (我目前没有为其设置动画),一些不可见的ViewHolder将逐渐重新可见(每次2-3个,直到它们都恢复正常可见性)

  • 然后,如果我调用
    notifyDataSetChanged()
    足够多的时间使整个堆栈再次可见,我就正好回到了开始的位置!动画将在一个删除->插入循环中正常工作,然后再次合并属性

一开始,我认为问题可能在于重用ViewHolder,它们以某种方式拥有相同的
itemView
,而旧的动画仍在附加。这就是为什么我在每个方法的开头都有
holder.itemView.clearAnimation()
行,但它对效果没有任何影响

我被难住了。特别是因为底部2个左右的视图持有者似乎对这种效果免疫,尽管他们可能经历了与其他所有人完全相同的过程。它总是在屏幕底部,不管我滚动到哪里,所以它与位置无关

不过,我肯定我还缺少一些东西(可能很多),因为这是我第一次与ItemAnimator广泛合作


任何帮助都将不胜感激。

我相信您所有的问题都归结于这样一个事实,即有时您的
ViewHolder
实例会被重复使用,有时则不会

我可以使用你发布的代码创建自己的应用程序,并重现你的问题。以下是我的虚拟应用程序在两次单击GO按钮后的外观:

这里发生的事情是,前五个
ViewHolder
s被重新使用和绑定,而接下来的五个是从头创建并首次绑定的。日志验证了这一点:

02-10 12:35:13.112  5754  5754 I System.out: binding view holder: 0
02-10 12:35:13.112  5754  5754 I System.out: binding view holder: 1
02-10 12:35:13.112  5754  5754 I System.out: binding view holder: 2
02-10 12:35:13.114  5754  5754 I System.out: binding view holder: 3
02-10 12:35:13.115  5754  5754 I System.out: binding view holder: 4
02-10 12:35:13.115  5754  5754 I System.out: creating view holder
02-10 12:35:13.116  5754  5754 I System.out: binding view holder: 5
02-10 12:35:13.116  5754  5754 I System.out: creating view holder
02-10 12:35:13.117  5754  5754 I System.out: binding view holder: 6
02-10 12:35:13.117  5754  5754 I System.out: creating view holder
02-10 12:35:13.117  5754  5754 I System.out: binding view holder: 7
02-10 12:35:13.117  5754  5754 I System.out: creating view holder
02-10 12:35:13.117  5754  5754 I System.out: binding view holder: 8
02-10 12:35:13.118  5754  5754 I System.out: creating view holder
02-10 12:35:13.118  5754  5754 I System.out: binding view holder: 9
由于前五个
ViewHolder
s已被重新使用,它们的
alpha
仍设置为
0
。。。毕竟,在“删除”过程中,您将alpha设置为0,但从未在任何地方将其设置为1。因此,只需在“删除”动画的
onAnimationEnd()
回调中添加以下内容:

holder.itemView.setAlpha(1);
.setStartDelay(0)
另一个问题(重叠的启动延迟)我不是很确定。我知道如何修复它,但我有点不清楚为什么修复会起作用。再一次,这个系统似乎正在接受旧的价值观。。。您为“添加”动画设置了开始延迟,但从未为“删除”动画明确设置开始延迟。。。因此,它选择了旧的“添加”延迟。只需将此添加到“删除”动画上的
animate()
链:

holder.itemView.setAlpha(1);
.setStartDelay(0)

有了这两个功能,我的虚拟应用程序似乎工作得很好。

我相信你所有的问题都归结于这样一个事实:有时你的
ViewHolder
实例会被重复使用,有时则不会

我可以使用你发布的代码创建自己的应用程序,并重现你的问题。以下是我的虚拟应用程序在两次单击GO按钮后的外观:

这里发生的事情是,前五个
ViewHolder
s被重新使用和绑定,而接下来的五个是从头创建并首次绑定的。日志验证了这一点:

02-10 12:35:13.112  5754  5754 I System.out: binding view holder: 0
02-10 12:35:13.112  5754  5754 I System.out: binding view holder: 1
02-10 12:35:13.112  5754  5754 I System.out: binding view holder: 2
02-10 12:35:13.114  5754  5754 I System.out: binding view holder: 3
02-10 12:35:13.115  5754  5754 I System.out: binding view holder: 4
02-10 12:35:13.115  5754  5754 I System.out: creating view holder
02-10 12:35:13.116  5754  5754 I System.out: binding view holder: 5
02-10 12:35:13.116  5754  5754 I System.out: creating view holder
02-10 12:35:13.117  5754  5754 I System.out: binding view holder: 6
02-10 12:35:13.117  5754  5754 I System.out: creating view holder
02-10 12:35:13.117  5754  5754 I System.out: binding view holder: 7
02-10 12:35:13.117  5754  5754 I System.out: creating view holder
02-10 12:35:13.117  5754  5754 I System.out: binding view holder: 8
02-10 12:35:13.118  5754  5754 I System.out: creating view holder
02-10 12:35:13.118  5754  5754 I System.out: binding view holder: 9
由于前五个
ViewHolder
s已被重新使用,它们的
alpha
仍设置为
0
。。。毕竟,在“删除”过程中,您将alpha设置为0,但从未在任何地方将其设置为1。因此,只需在“删除”动画的
onAnimationEnd()
回调中添加以下内容:

holder.itemView.setAlpha(1);
.setStartDelay(0)
另一个问题(重叠的启动延迟)我不是很确定。我知道怎么修,但我是个l