RecyclerView ItemTouchHelper滑动删除动画

Rok*_*okG 15 android swipe android-recyclerview

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

    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);
            }
        });
Run Code Online (Sandbox Code Playgroud)

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

    public void remove(int position) {
       items.remove(position);
       notifyItemRemoved(position);
    }
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述 在此输入图像描述

我希望它保留背景,同时它(就像收件箱应用程序一样).有没有办法做到这一点?

Nem*_*vic 5

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

无论如何,当行动画时回到背景:我无法在ItemTouchHelper和 中做到这一点onChildDraw。最后我不得不添加另一个项目装饰器来完成它。它沿着这些路线:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

当我说您的 ItemTouchHelper 绘制太多时,我的意思是:看起来像ItemTouchHelper保留ViewHolder已删除的行,以防需要恢复。onChildDraw除了刷过的 VH 之外,它还需要那些 VH。不确定这种行为对内存管理的影响,但我需要在开始时onChildDraw进行额外检查以避免绘制“fantom”行。

if (viewHolder.getAdapterPosition() == -1) {
    return;
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:我尝试了一下,请参阅此博客文章和此github repo