我正在使用RecyclerView
使用SortedList
来提取来自SortedListAdapterCallback
的数据。我想停用onChange
个活动的动画,但要为onInserted
/ onRemoved
/ onMoved
保留动画。我尝试在setSupportsChangeAnimations(false)
使用的DefaultItemAnimator
上调用RecyclerView
,但仍会显示动画。如果我致电setItemAnimator(null)
,则所有动画都会按预期成功删除。
我尝试查看实现,看起来如果supportsChangeAnimations
是true
,RecyclerView
会通过保留旧的viewHolder并将其交叉淡化到新的viewHolder来为更改事件设置动画。我不想要那个。如果supportsChangeAnimations
为false
,旧的和新的viewHolders将是同一个对象,而是从x到x的onMoved
动画(即没有实际移动)。然而,这意味着该项目将产生令人讨厌的反弹效果。我也不想要那个,我根本不需要动画。 :(
来自DefaultItemAnimator.java:
@Override
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) {
if (oldHolder == newHolder) {
// Don't know how to run change animations when the same view holder is re-used.
// run a move animation to handle position changes.
return animateMove(oldHolder, fromX, fromY, toX, toY);
}
...
有时当我加载我的列表时,我会异步地获取一些数据并将项目更新1-3次,并且每当它反弹和闪烁时它看起来真的很糟糕。
如何在不诉诸编写完全自定义的ItemAnimator的情况下有效完全禁用onChange
动画?
答案 0 :(得分:6)
查看代码(我使用支持库25.2.0):setSupportsChangeAnimations(<value>)
是抽象类SimpleItemAnimator
上的一种方法,它也是DefaultItemAnimator
&#39 ; s超类。在内部,它修改了mSupportsChangeAnimations
。
在DefaultItemAnimator
代码中执行文字搜索,发现既未查询mSupportsChangeAnimations
也未查询getSupportsChangeAnimations()
- &gt; DefaultItemAnimator
字面上忽略了这个标志。
正确的解决方案是以下列方式扩展DefaultItemAnimator
:
public class CustomItemAnimator extends DefaultItemAnimator {
@Override
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
if (getSupportsChangeAnimations()) {
return super.animateChange(oldHolder, newHolder, fromX, fromY, toX, toY);
} else {
if (oldHolder == newHolder) {
if (oldHolder != null) {
//if the two holders are equal, call dispatch change only once
dispatchChangeFinished(oldHolder, /*ignored*/true);
}
} else {
//else call dispatch change once for every non-null holder
if (oldHolder != null) {
dispatchChangeFinished(oldHolder, true);
}
if (newHolder != null) {
dispatchChangeFinished(newHolder, false);
}
}
//we don't need a call to requestPendingTransactions after this, return false.
return false;
}
}
请参阅文档animateChange(...)
,了解为什么在没有动画运行时需要调用dispatchChangeFinished(...)
。
当没有要运行的动画时,可能有一种更优雅的方式来编写else分支,但是,这可以实现所需的行为。
最近很亲切,但希望这有帮助!
答案 1 :(得分:4)
上面的解决方案对我来说对25.3.1的支持库版本不起作用,因为我想禁用所有回收器视图项的动画。我通过覆盖 userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
userViewModel.getUserList().observe(UserListActivity.this, new
Observer<List<User>>() {
@Override
public void onChanged(@Nullable List<User> user) {
adapter.addItems(user);
}
});
:
SimpleItemAnimator
答案 2 :(得分:3)
在这个聚会上我来晚了一点,但是使用androidx.recyclerview:recyclerview:1.1.0
,我可以将默认动画师的changeDuration
的更改设置为0,这样可以有效地禁用动画,同时允许添加/移动/删除动画以继续正常运行。无需自定义覆盖DefaultItemAnimator
。
示例(在Kotlin中):
view.my_recycler_view.itemAnimator?.changeDuration = 0