Android - 轻扫以删除RecyclerView

时间:2015-11-29 17:28:55

标签: android android-recyclerview

我正在尝试实施滑动以删除与Gmail应用相同的内容"滑动以存档":

gmail swipe delete gmail swipe delete

我尝试了很多教程,但没有一个像gmail一样快, 我更喜欢不在外部库上工作。我该怎么办?

编辑:

到目前为止我的代码 -

  ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
                public boolean onMove(RecyclerView recyclerView,
                                               RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
//                    final int fromPos = viewHolder.getAdapterPosition();
//                    final int toPos = viewHolder.getAdapterPosition();
//                    // move item in `fromPos` to `toPos` in adapter.
                    return true;// true if moved, false otherwise
                }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
                //Remove swiped item from list and notify the RecyclerView
                mAdapter.notifyItemRemoved(viewHolder.getLayoutPosition());
            }
        };
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
        itemTouchHelper.attachToRecyclerView(mRecyclerView);

我设法启用了滑动手势,但我不知道如何在viewHolder 下添加背景和图片。我试图将另一个FrameLayout放在item_XXX.xml文件中,但是在滑动时它会抛出整个项目的背景。

6 个答案:

答案 0 :(得分:25)

RecyclerView Swipe的简单代码:

     ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT | ItemTouchHelper.DOWN | ItemTouchHelper.UP) {

            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                Toast.makeText(ListActivity.this, "on Move", Toast.LENGTH_SHORT).show();
                return false;
            }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
                Toast.makeText(ListActivity.this, "on Swiped ", Toast.LENGTH_SHORT).show();
                //Remove swiped item from list and notify the RecyclerView
                int position = viewHolder.getAdapterPosition();
                arrayList.remove(position);
                adapter.notifyDataSetChanged();

            }
     };

然后使用以下语句为recyclelerView设置回调:

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
 itemTouchHelper.attachToRecyclerView(rv);

答案 1 :(得分:24)

前几天我不得不这样做,我遇到了一些问题所以我决定写一篇博文。不需要第三方库。

基本上,您不会通过onChildDraw绘制“撤消状态”,而是通过ViewHolder完成。另外,您实际上不会删除onSwipe中的行,只需将其标记为“待删除”,并通知适配器以“撤消状态”重新绑定它。同时你发布Runnable实际上在x秒内删除行除非按下撤销按钮...

答案 2 :(得分:1)

您可以尝试Swipeable-RecyclerView

    SwipeableRecyclerView rv = findViewById(R.id.rv);
    rv.setLayoutManager(new LinearLayoutManager(this));
    rv.setAdapter(mAdapter);

    rv.setListener(new SwipeLeftRightCallback.Listener() {
        @Override
        public void onSwipedLeft(int position) {
            mList.remove(position);
            mAdapter.notifyDataSetChanged();
        }

        @Override
        public void onSwipedRight(int position) {
            mList.remove(position);
            mAdapter.notifyDataSetChanged();
        }
    });
两侧滑动的

xml

<com.tsuryo.swipeablerv.SwipeableRecyclerView
    android:id="@+id/rv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:leftBgColor="@color/colorAccent"
    app:leftImage="@drawable/ic_remove"
    app:leftText="Delete"
    app:rightBgColor="@color/blue"
    app:rightImage="@drawable/ic_check"
    app:rightText="Read"
    app:textColor="@android:color/white"
    app:textSize="20sp" />

答案 3 :(得分:1)

这是您的onCreate中设置“向左轻扫以删除”的最小代码:

        binding.rows.adapter = adapter
        ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
            override fun onMove(v: RecyclerView, h: RecyclerView.ViewHolder, t: RecyclerView.ViewHolder) = false
            override fun onSwiped(h: RecyclerView.ViewHolder, dir: Int) = adapter.removeAt(h.adapterPosition)
        }).attachToRecyclerView(binding.rows)

这假设您的Adapter类具有removeAt函数。我的看起来像这样:

            fun removeAt(index: Int) {
                items.removeAt(index)   // items is a MutableList
                notifyItemRemoved(index)
            }

感谢@RahulRaina您的Java回答!

答案 4 :(得分:-1)

完全基于@RahulRaina答案

new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView,
                          @NonNull RecyclerView.ViewHolder viewHolder,
                          @NonNull RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        ((ItemsAdapter.ViewHolder) viewHolder).remove();
    }
}).attachToRecyclerView(binding.recyclerView);

在我的适配器命名为ItemsAdapter的情况下,其视图持有者是其子类,并在其中命名为ViewHolder,并且remove方法除持久保存数据外,还应调用notifyDataSetChanged()

答案 5 :(得分:-2)

这肯定会奏效。如果你想要小吃店,那么在你的xml中使用coordinatorLayout。您可以像gmail一样设置背景。如果您有任何想法,只需点击链接

即可

https://drive.google.com/open?id=11ZOrjMMSjdskt8gG8RP52V5Al5yE50dD

  ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)

      {

                Drawable background;
                Drawable xMark;
                int xMarkMargin;
                boolean initiated;

                private void init() {
                    background = new ColorDrawable(Color.RED);
                    xMark = ContextCompat.getDrawable(Activity.this, R.drawable.ic_delete_svg);
                    xMark.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
                    initiated = true;
                }

                @Override
                public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                    Toast.makeText(Activity.this, "on Move", Toast.LENGTH_SHORT).show();
                    return false;
                }

                @Override
                public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
                    /*Toast.makeText(mcontext, "on Swiped ", Toast.LENGTH_SHORT).show();*/

                    Snackbar snackbar = Snackbar
                            .make(coordinatorLayout, "Deleted Successfully", Snackbar.LENGTH_LONG)
                            .setAction("UNDO", new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    Snackbar snackbar1 = Snackbar.make(coordinatorLayout, "Message is restored!", Snackbar.LENGTH_SHORT);
                                    snackbar1.show();
                                }
                            });

                    snackbar.show();

                    //Remove swiped item from list and notify the RecyclerView
                    int position = viewHolder.getAdapterPosition();
                    arrayList.remove(position);
                    adapter.notifyDataSetChanged();

                }

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

                    // not sure why, but this method get's called for viewholder that are already swiped away
                    if (viewHolder.getAdapterPosition() == -1) {
                        // not interested in those
                        return;
                    }

                    if (!initiated) {
                        init();
                    }

                    // draw red background
                    background.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom());
                    background.draw(c);

                    int xMarkLeft = 0;
                    int xMarkRight = 0;
                    int xMarkTop = itemView.getTop() + (itemHeight - intrinsicHeight) / 2;
                    int xMarkBottom = xMarkTop + intrinsicHeight;
                    if (dX < 0) {
                        xMarkLeft = itemView.getRight() - xMarkMargin - intrinsicWidth;
                        xMarkRight = itemView.getRight() - xMarkMargin;
                    } else {
                        xMarkLeft = itemView.getLeft() + xMarkMargin;
                        xMarkRight = itemView.getLeft() + xMarkMargin + intrinsicWidth;
                    }
                    xMark.setBounds(xMarkLeft, xMarkTop, xMarkRight, xMarkBottom);
                    xMark.draw(c);

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

            };


            ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
            itemTouchHelper.attachToRecyclerView(mRecyclerView);