Rom*_*nko 32 animation android android-recyclerview
的RecyclerView,不像到ListView,没有一个简单的方法来设置空视图,所以人们必须手动管理它,使空视图在适配器的项目数的情况下,可见是0.
实现这一点,起初我尝试在修改底层结构(ArrayList在我的情况下)后立即调用空视图逻辑,例如:
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();
}
});
Run Code Online (Sandbox Code Playgroud)
它做了这件事,但有一个缺点:当删除最后一个元素时,在删除动画完成之前立即显示空视图.所以我决定等到动画结束然后更新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();
}
});
}
});
Run Code Online (Sandbox Code Playgroud)
不幸的是,在这种情况下回调立即运行,因为在那一刻内部ItemAnimator仍然没有处于"运行"状态.所以,问题是:如何正确使用ItemAnimator.isRunning()方法,是否有更好的方法来实现所需的结果,即在单个元素的删除动画完成后显示空视图?
Rom*_*nko 19
目前我发现解决这个问题的唯一工作方式是扩展ItemAnimator并传递给它RecyclerView:
recyclerView.setItemAnimator(new DefaultItemAnimator() {
@Override
public void onAnimationFinished(RecyclerView.ViewHolder viewHolder) {
updateEmptyView();
}
});
Run Code Online (Sandbox Code Playgroud)
但是这种技术并不普遍,因为我必须从ItemAnimator正在使用的具体实现扩展RecyclerView.在CoolItemAnimator内部私有的情况下CoolRecyclerView,我的方法根本不起作用.
PS:我的同事建议包裹ItemAnimator内装饰以下列方式:
recyclerView.setItemAnimator(new ListenableItemAnimator(recyclerView.getItemAnimator()));
Run Code Online (Sandbox Code Playgroud)
这将是很好,尽管看起来矫枉过正这样一个简单的任务,但在这种情况下产生的装饰是不可能的,无论如何,是因为ItemAnimator有一个方法setListener()是包保护的,所以我显然不能把它包装,还有一些最后的方法.
nib*_*ius 12
我有一个更通用的案例,我想要检测回收器视图何时完全动画完成,同时删除或添加一个或多个项目.
我尝试过Roman Petrenko的答案,但在这种情况下它不起作用.问题是onAnimationFinished在回收器视图中为每个条目调用.大多数条目没有改变,因此onAnimationFinished或多或少地被称为瞬时.但是对于添加和删除动画需要一点时间,因此稍后会调用它.
这导致至少两个问题.假设您有一个doStuff()在动画完成时要运行的方法.
如果您只是打电话doStuff(),onAnimationFinished您将为回收站视图中的每个项目调用一次,这可能不是您想要做的.
如果你doStuff()第一次onAnimationFinished打电话,你可能会在最后一个动画完成之前很久就打电话.
如果您可以知道要动画的项目数量,您可以确保doStuff()在上一个动画结束时调用.但我还没有找到任何方法知道有多少剩余的动画排队等候.
我对此问题的解决方案是让回收器视图首先通过使用启动动画new Handler().post(),然后设置一个侦听器isRunning(),并在动画准备好时调用该侦听器.之后,它重复该过程,直到所有视图都被动画化.
void changeAdapterData() {
// ...
// Changes are made to the data held by the adapter
recyclerView.getAdapter().notifyDataSetChanged();
// The recycler view have not started animating yet, so post a message to the
// message queue that will be run after the recycler view have started animating.
new Handler().post(waitForAnimationsToFinishRunnable);
}
private Runnable waitForAnimationsToFinishRunnable = new Runnable() {
@Override
public void run() {
waitForAnimationsToFinish();
}
};
// When the data in the recycler view is changed all views are animated. If the
// recycler view is animating, this method sets up a listener that is called when the
// current animation finishes. The listener will call this method again once the
// animation is done.
private void waitForAnimationsToFinish() {
if (recyclerView.isAnimating()) {
// The recycler view is still animating, try again when the animation has finished.
recyclerView.getItemAnimator().isRunning(animationFinishedListener);
return;
}
// The recycler view have animated all it's views
onRecyclerViewAnimationsFinished();
}
// Listener that is called whenever the recycler view have finished animating one view.
private RecyclerView.ItemAnimator.ItemAnimatorFinishedListener animationFinishedListener =
new RecyclerView.ItemAnimator.ItemAnimatorFinishedListener() {
@Override
public void onAnimationsFinished() {
// The current animation have finished and there is currently no animation running,
// but there might still be more items that will be animated after this method returns.
// Post a message to the message queue for checking if there are any more
// animations running.
new Handler().post(waitForAnimationsToFinishRunnable);
}
};
// The recycler view is done animating, it's now time to doStuff().
private void onRecyclerViewAnimationsFinished() {
doStuff();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10970 次 |
| 最近记录: |