RecyclerView ItemTouchHelper 滑动移除动画 [英] RecyclerView ItemTouchHelper swipe remove animation

查看:29
本文介绍了RecyclerView ItemTouchHelper 滑动移除动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个删除滑动,绘制背景(很像收件箱应用程序),由 ItemTouchHelper 实现 - 通过覆盖 onChilDraw 方法并在提供的画布上绘制一个矩形:

I've got a remove on swipe, that draws a background (much like the Inbox app), implemented by an ItemTouchHelper - by overriding the onChilDraw method and drawing a rectangle on the provided canvas:

    ItemTouchHelper mIth = new ItemTouchHelper(
        new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {

            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                remove(viewHolder.getAdapterPosition());
            }

            public boolean onMove(RecyclerView recyclerview, RecyclerView.ViewHolder v, RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {

                View itemView = viewHolder.itemView;

                Drawable d = ContextCompat.getDrawable(context, R.drawable.bg_swipe_item_right);
                d.setBounds(itemView.getLeft(), itemView.getTop(), (int) dX, itemView.getBottom());
                d.draw(c);

                super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
            }
        });

上面调用的remove方法在Adapter中:

The remove method called above is in the Adapter:

    public void remove(int position) {
       items.remove(position);
       notifyItemRemoved(position);
    }

背景绘制得很好,但是当调用notifyItemRemoved时(根据Debugger先生的说法),RecyclerView首先删除了我漂亮的绿色背景,然后将两个相邻的项目推到了一起.

The background draws out nicely, but when notifyItemRemoved is called (according to Mr. Debugger), the RecyclerView first deletes my pretty green background, and then pushes the two adjacent items together.

我希望它在执行此操作时将背景保留在那里(就像 Inbox 应用程序一样).有没有办法做到这一点?

I would like it to keep the background there while it does that (just like the Inbox app). Is there any way to do that?

推荐答案

我遇到了同样的问题,我不想引入一个新的库来解决它.RecyclerView 不会删除您漂亮的绿色背景,它只是重新绘制自己,而您的 ItemTouchHelper 不再绘制了.实际上它正在绘图,但 dX 为 0 并且正在从 itemView.getLeft()(即 0)到 dX(即 0) 所以你什么也看不见.画的太多了,我稍后再回来.

I had the same issue and I didn't wanna introduce a new lib just to fix it. The RecyclerView is not deleting your pretty green background, it's just redrawing itself, and your ItemTouchHelper is not drawing anymore. Actually it's drawing but the dX is 0 and is drawing from the itemView.getLeft() (which is 0) to dX (which is 0) so you see nothing. And it's drawing too much, but I'll come back to it later.

无论如何在行动画时回到背景:我无法在 ItemTouchHelperonChildDraw 中做到这一点.最后我不得不添加另一个项目装饰器来完成它.它遵循以下路线:

Anyway back to the background while rows animate: I couldn't do it within ItemTouchHelper and onChildDraw. In the end I had to add another item decorator to do it. It goes along these lines:

public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    if (parent.getItemAnimator().isRunning()) {
        // find first child with translationY > 0
        // draw from it's top to translationY whatever you want

        int top = 0;
        int bottom = 0;

        int childCount = parent.getLayoutManager().getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getLayoutManager().getChildAt(i);
            if (child.getTranslationY() != 0) {
                top = child.getTop();
                bottom = top + (int) child.getTranslationY();                    
                break;
            }
        }

        // draw whatever you want

        super.onDraw(c, parent, state);
    }
}

此代码仅考虑向上动画的行,但您还应该考虑向下的行.如果您滑动删除最后一行,就会发生这种情况,上面的行将向下移动到该空间.

This code takes into account only rows animating up, but you should also consider rows coming down. That happens if you swipe delete the last row, rows above are gonna animate down to that space.

当我说您的 ItemTouchHelper 绘制太多时,我的意思是:看起来 ItemTouchHelper 保留了已删除行的 ViewHolder 以备需要恢复.除了正在滑动的 VH 之外,它还为那些 VH 调用 onChildDraw.不确定此行为对内存管理的影响,但我需要在 onChildDraw 的开头进行额外检查,以避免绘制fantom"行.

When I said your ItemTouchHelper is drawing too much what I meant was: Looks like ItemTouchHelper keeps ViewHolders of removed rows in case they need to be restored. It's also calling onChildDraw for those VHs in addition to the VH being swiped. Not sure about memory management implications of this behavior but I needed an additional check in the start of onChildDraw to avoid drawing for "fantom" rows.

if (viewHolder.getAdapterPosition() == -1) {
    return;
}

在您的情况下,它是从 left=0 到 right=0 绘制的,因此您什么也看不到,但开销就在那里.如果您开始看到先前被刷掉的行绘制了它们的背景,这就是原因.

In your case it's drawing from left=0 to right=0 so you don't see anything but the overhead is there. If you start seeing previously swiped away rows drawing their backgrounds that is the reason.

我试了一下,见这个博文 和这个github 存储库.

I had a go at this, see this blog post and this github repo.

这篇关于RecyclerView ItemTouchHelper 滑动移除动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆