在 RecyclerView.Adapter 中覆盖 notifyItemChanged 的动画
Override animation for notifyItemChanged in RecyclerView.Adapter
好吧,我有一个带适配器的 RecyclerView,一切正常。 ArrayList 数据集中的项目会定期更新。因此,项目及其元素以及它们在列表中的位置会发生变化。这是通过简单的排序和手动调用这些方法来实现的,无论何时发生:
// swapping two items
Collections.swap(items, i, j);
itemsAdapter.notifyItemMoved(i, j);
// adding a new one
itemAdapter.notifyItemInserted(items.size());
// when updating valus
itemAdapter.notifyItemChanged(i);
后者是我痛苦的原因。每次更新项目时,都会触发一点 "blink" 动画。
我找到了几个解决方案:
// disabling all animations
recyclerView.getItemAnimator().setSupportsChangeAnimations(false);
// or
// setting the animation duration to zero,
recyclerView.getItemAnimator().setChangeDuration(0);
但是当项目移动(被交换)时,这两个都会杀死动画。我只想覆盖一个动画并保留所有这些魔法。有没有办法做到这一点?如果它重写 ItemAnimator,有没有人有一个简单的例子?
提前致谢!
是的,我做到了。
首先获取DefaultItemAnimator的源码。获取代码并在您的项目中创建一个名为 MyItemAnimator 的 class。然后,将 ItemAnimator 设置为修改后的 MyItemAnimator 的新实例,如下所示:
recyclerView.setItemAnimator(new MyItemAnimator());
现在,进入新的 classes 源代码并找到方法
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() { ... }
Alex 的回答略有不同。
我没有完全删除 alpha 更改,而是减少了它。唯一需要的改变是:
//changed alpha from 0
ViewCompat.setAlpha(newHolder.itemView, 0.5f);
和
//changed alpha from 0
oldViewAnim.alpha(0.5f).setListener(new VpaListenerAdapter() {
在这两种情况下,将 0 更改为 0.5
这具有消除与 alpha 完全变为 0 相关的闪烁的效果,但保留项目更改动画的变形质量。
有一种专门的方法可以禁用仅项目更改的动画:
((SimpleItemAnimator) myRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
在我的例子中,recyclerview 占用了工具栏下方的所有 space。我所做的只是将 recyclerview 的 layout_height 从 wrap_content 更改为 match_parent 并且闪烁消失了。
如果你只是修改Recyclerview的数据意味着没有添加或删除项目那么你应该添加这一行。
mRecyclerview.setHasFixedSize(true);
这样recyclerview就会知道大小没有变化之后你就可以申请了
((SimpleItemAnimator) mRecyclerview.getItemAnimator()).setSupportsChangeAnimations(false);
这样动画就会消失,代码就会像魅力一样工作:)
尝试设置:
mRecyclerview.setItemAnimator(null);
Kotlin 版本 答案:
(recyclerView.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
好吧,我有一个带适配器的 RecyclerView,一切正常。 ArrayList 数据集中的项目会定期更新。因此,项目及其元素以及它们在列表中的位置会发生变化。这是通过简单的排序和手动调用这些方法来实现的,无论何时发生:
// swapping two items
Collections.swap(items, i, j);
itemsAdapter.notifyItemMoved(i, j);
// adding a new one
itemAdapter.notifyItemInserted(items.size());
// when updating valus
itemAdapter.notifyItemChanged(i);
后者是我痛苦的原因。每次更新项目时,都会触发一点 "blink" 动画。
我找到了几个解决方案:
// disabling all animations
recyclerView.getItemAnimator().setSupportsChangeAnimations(false);
// or
// setting the animation duration to zero,
recyclerView.getItemAnimator().setChangeDuration(0);
但是当项目移动(被交换)时,这两个都会杀死动画。我只想覆盖一个动画并保留所有这些魔法。有没有办法做到这一点?如果它重写 ItemAnimator,有没有人有一个简单的例子?
提前致谢!
是的,我做到了。
首先获取DefaultItemAnimator的源码。获取代码并在您的项目中创建一个名为 MyItemAnimator 的 class。然后,将 ItemAnimator 设置为修改后的 MyItemAnimator 的新实例,如下所示:
recyclerView.setItemAnimator(new MyItemAnimator());
现在,进入新的 classes 源代码并找到方法
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() { ... }
Alex 的回答略有不同。
我没有完全删除 alpha 更改,而是减少了它。唯一需要的改变是:
//changed alpha from 0
ViewCompat.setAlpha(newHolder.itemView, 0.5f);
和
//changed alpha from 0
oldViewAnim.alpha(0.5f).setListener(new VpaListenerAdapter() {
在这两种情况下,将 0 更改为 0.5 这具有消除与 alpha 完全变为 0 相关的闪烁的效果,但保留项目更改动画的变形质量。
有一种专门的方法可以禁用仅项目更改的动画:
((SimpleItemAnimator) myRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
在我的例子中,recyclerview 占用了工具栏下方的所有 space。我所做的只是将 recyclerview 的 layout_height 从 wrap_content 更改为 match_parent 并且闪烁消失了。
如果你只是修改Recyclerview的数据意味着没有添加或删除项目那么你应该添加这一行。
mRecyclerview.setHasFixedSize(true);
这样recyclerview就会知道大小没有变化之后你就可以申请了
((SimpleItemAnimator) mRecyclerview.getItemAnimator()).setSupportsChangeAnimations(false);
这样动画就会消失,代码就会像魅力一样工作:)
尝试设置:
mRecyclerview.setItemAnimator(null);
Kotlin 版本
(recyclerView.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false