RecyclerView
与ListView
不同,它没有一种简单的方法来为其设置空白 View ,因此必须手动对其进行管理,以使空白 View 在适配器的项目计数为0时可见。
实现这一点,首先,我尝试在修改底层结构(在我的情况下为ArrayList
)之后立即调用空 View 逻辑,例如:
btnRemoveFirst.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
devices.remove(0); // remove item from ArrayList
adapter.notifyItemRemoved(0); // notify RecyclerView's adapter
updateEmptyView();
}
});
它可以执行此操作,但有一个缺点:当删除最后一个元素时,在删除动画完成之前,紧接在删除之后,空 View 出现。因此,我决定等到动画结束后再更新UI。
令我惊讶的是,我找不到在RecyclerView中收听动画事件的好方法。首先想到的是使用
isRunning
方法,如下所示:btnRemoveFirst.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
devices.remove(0); // remove item from ArrayList
adapter.notifyItemRemoved(0); // notify RecyclerView's adapter
recyclerView.getItemAnimator().isRunning(new RecyclerView.ItemAnimator.ItemAnimatorFinishedListener() {
@Override
public void onAnimationsFinished() {
updateEmptyView();
}
});
}
});
不幸的是,在这种情况下,回调会立即运行,因为那一刻内部
ItemAnimator
仍未处于“运行”状态。因此,问题是:如何正确使用ItemAnimator.isRunning()方法,并且有一种更好的方法来实现所需的结果,即在单个元素的删除动画完成后显示空 View 吗? 最佳答案
目前,我发现解决此问题的唯一可行方法是扩展ItemAnimator
并将其传递给RecyclerView
,如下所示:
recyclerView.setItemAnimator(new DefaultItemAnimator() {
@Override
public void onAnimationFinished(RecyclerView.ViewHolder viewHolder) {
updateEmptyView();
}
});
但是这种技术不是通用的,因为我必须从
ItemAnimator
使用的具体RecyclerView
实现中扩展。如果在CoolItemAnimator
内部有私有(private)内部CoolRecyclerView
,我的方法将根本无法工作。PS:我的同事建议以以下方式将
ItemAnimator
包装在decorator中:recyclerView.setItemAnimator(new ListenableItemAnimator(recyclerView.getItemAnimator()));
很好,尽管似乎对于这样一个琐碎的任务来说过于矫kill过正,但是在这种情况下,无论如何都无法创建装饰器,因为
ItemAnimator
具有setListener()
方法,该方法受程序包保护,因此我显然无法包装它 final方法。