问题描述
RecyclerView
与 ListView
不同,它没有简单的方法来设置空视图,所以必须手动管理它,创建空视图在适配器的项目计数为 0 的情况下可见.
The RecyclerView
, unlike to ListView
, doesn't have a simple way to set an empty view to it, so one has to manage it manually, making empty view visible in case of adapter's item count is 0.
实现这个,一开始我尝试在修改底层结构后立即调用空视图逻辑(在我的例子中是ArrayList
),例如:
Implementing this, at first I tried to call empty view logic right after modifying underlaying structure (ArrayList
in my case), for example:
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();
}
});
它可以做到这一点,但有一个缺点:当最后一个元素被移除时,空视图在移除动画完成之前出现,在移除之后立即出现.所以我决定等到动画结束再更新UI.
It does the thing, but has a drawback: when the last element is being removed, empty view appears before animation of removing is finished, immediately after removal. So I decided to wait until end of animation and then update UI.
令我惊讶的是,我找不到在 RecyclerView 中监听动画事件的好方法.首先想到的是像这样使用 isRunning
方法:
To my surprise, I couldn't find a good way to listen for animation events in RecyclerView. First thing coming to mind is to use isRunning
method like this:
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()方法,有没有更好的方法来达到预期的效果,即在移除单个元素的动画后显示空视图是完成?
Unfortunately, callback in this case runs immediately, because at that moment inner ItemAnimator
still isn't in the "running" state. So, the questions are: how to properly use ItemAnimator.isRunning() method and is there a better way to achieve the desired result, i.e. show empty view after removal animation of the single element is finished?
推荐答案
目前我发现解决这个问题的唯一可行方法是扩展 ItemAnimator
并将其传递给 RecyclerView
像这样:
Currently the only working way I've found to solve this problem is to extend ItemAnimator
and pass it to RecyclerView
like this:
recyclerView.setItemAnimator(new DefaultItemAnimator() {
@Override
public void onAnimationFinished(RecyclerView.ViewHolder viewHolder) {
updateEmptyView();
}
});
但这种技术并不通用,因为我必须从 RecyclerView
使用的具体 ItemAnimator
实现进行扩展.如果 CoolRecyclerView
内部有私有内部 CoolItemAnimator
,我的方法将根本不起作用.
But this technique is not universal, because I have to extend from concrete ItemAnimator
implementation being used by RecyclerView
. In case of private inner CoolItemAnimator
inside CoolRecyclerView
, my method will not work at all.
PS:我的同事建议将 ItemAnimator
包装在 装饰器 以如下方式:
PS: My colleague suggested to wrap ItemAnimator
inside the decorator in a following manner:
recyclerView.setItemAnimator(new ListenableItemAnimator(recyclerView.getItemAnimator()));
这会很好,尽管对于这样一个微不足道的任务来说似乎有点矫枉过正,但无论如何在这种情况下创建装饰器是不可能的,因为 ItemAnimator
有一个方法 setListener()
是包保护的,所以我显然不能包装它,还有几个 final 方法.
It would be nice, despite seems like overkill for a such trivial task, but creating the decorator in this case is not possible anyway, because ItemAnimator
has a method setListener()
which is package protected so I obviously can't wrap it, as well as several final methods.
这篇关于在 Android 的 RecyclerView 中检测动画完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!