RecyclerViewListView不同,它没有一种简单的方法来为其设置空白 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方法。

10-06 10:23