本文介绍了在 Android 的 RecyclerView 中检测动画完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

RecyclerViewListView 不同,它没有简单的方法来设置空视图,所以必须手动管理它,创建空视图在适配器的项目计数为 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 中检测动画完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-15 05:07