滑动以关闭RecyclerView [关闭]


116

我曾经使用过SwipeToDismiss库,但现在我正尝试迁移到RecyclerView,事情并不是那么明显,您知道此lib有任何替换吗?有什么想法如何从头开始实施它吗?


1
我已经制作了一个小型库,该库使用ItemTouchHelper简化了recyclerview的手势创建,您可以在这里找到它github.com/olmur/rvtools
Olexii Muraviov,2017年

Answers:


336

从v22.2.0开始,Android支持团队提供了一个ItemTouchHelper类,该类使轻扫到关闭和拖放变得非常简单。它可能不像那里的某些库那样功能齐全,但是它直接来自Android团队。

  • 更新您的build.gradle以导入v22.2。+的RecyclerView库

    compile 'com.android.support:recyclerview-v7:22.2.+'
  • 使用适当的SimpleCallback实例化ItemTouchHelper

    ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
        [...]
        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
            //Remove swiped item from list and notify the RecyclerView
        }
    };
    
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
    

    **请注意,SimpleCallback接受要启用拖放的方向以及要启用滑动的方向。

  • 附加到您的RecyclerView

    itemTouchHelper.attachToRecyclerView(recyclerView);

7
如何获得刷卡项目的索引?
MaTTo

37
@Orochi通过调用getAdapterPosition()viewHolder
SqueezyMo 2015年

1
他们显然对此组件的设计没有过多考虑。它仅适用于RecyclerView。小吃店等商品存在滑动到关闭的功能。可以用于任何视图的更通用的组件将受到更多欢迎。
AndroidDev

4
如果我要处理用户部分滑动然后将视图拖回原位的情况该怎么办?显然,这不是possibile(?)编辑:好的,它是可能的,但是在视图被释放之前,您可以留有很少的余量。有什么建议吗?
Matteo

2
@Matteo:实现ItemTouchHelper.Callback并覆盖getSwipeThreshold()
Sofi Software LLC

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

        @Override
        public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
            final int position = viewHolder.getAdapterPosition(); //get position which is swipe

            if (direction == ItemTouchHelper.LEFT) {    //if swipe left

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); //alert for confirm to delete
                builder.setMessage("Are you sure to delete?");    //set message

                builder.setPositiveButton("REMOVE", new DialogInterface.OnClickListener() { //when click on DELETE
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        adapter.notifyItemRemoved(position);    //item removed from recylcerview
                        sqldatabase.execSQL("delete from " + TABLE_NAME + " where _id='" + (position + 1) + "'"); //query for delete
                        list.remove(position);  //then remove item

                        return;
                    }
                }).setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {  //not removing items if cancel is done
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        adapter.notifyItemRemoved(position + 1);    //notifies the RecyclerView Adapter that data in adapter has been removed at a particular position.
                        adapter.notifyItemRangeChanged(position, adapter.getItemCount());   //notifies the RecyclerView Adapter that positions of element in adapter has been changed from position(removed element index to end of list), please update it.
                        return;
                    }
                }).show();  //show alert dialog
            }
        }
    };
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
    itemTouchHelper.attachToRecyclerView(recyclerView); //set swipe to recylcerview

在代码中,如果用户向左滑动,则会显示AlertDialog,如果用户选择REMOVE,则将从数据库中删除该项目,并刷新recyclerview;如果用户选择CANCEL,则recyclerview保持原样。


工作很好..不错的答案。
Sagar Chavada '17

太棒了!如此容易实现
dianakarenms

1
您真的不需要方向检查,if (direction == ItemTouchHelper.LEFT) // if swipe left因为ItemTouchHelper.SimpleCallback仅限于该滑动方向。如果要左右滑动ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT),则需要检查方向。
Jacko

1
我发现在AlertDialog外部单击可以取消对话框,但没有将我刷过的项目放回去。您可以捕获到将OnCancelListener添加到Builder的过程AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // stuff to put the item back } });
Jacko

1
+1运作良好。我发现adapter.notifyItemChanged(position);把刷过的物品带回来了,而不是notifyItemRemoved-更合乎逻辑的恕我直言。
Winwaed

14

也许您可以尝试以下库:

https://github.com/daimajia/AndroidSwipeLayout

更新:我刚刚找到了另一个可以与RecyclerView一起使用的好的库:

https://github.com/hudomju/android-swipe-to-dismiss-undo


我做了自己的实现,类似于github.com/krossovochkin/Android-SwipeToDismiss-RecyclerView。唯一的要求是显示带有“撤消”按钮的Toast,这在lib中没有涉及。
维克多·亚库宁

1
Daimajia的图书馆不支持滑动到关闭功能。
akohout 2015年

@raveN我刚刚更新了我的答案。
2015年


2

我写了SwipeToDeleteRV库,该库支持回收者视图上的“刷卡删除删除”功能。它基于ItemTouchHelper,非常易于使用。

希望对面临相同问题的人有所帮助。

例如,您可以按常规在XML布局中定义回收者视图,以及一些可选属性:

...
xmlns:stdrv="http://schemas.android.com/apk/res-auto"
...
<io.huannguyen.swipetodeleterv.STDRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
stdrv:border_color="@android:color/darker_gray" // specify things like border color, border width, etc.
stdrv:delete_view_background="#cccccc"
stdrv:delete_icon="@drawable/ic_archive"
stdrv:delete_icon_height="24dp"
stdrv:delete_icon_width="24dp"
stdrv:left_delete_icon_margin="32dp"
stdrv:delete_message="@string/delete_message"
stdrv:right_delete_icon_margin="32dp"
stdrv:delete_icon_color="#000000"
stdrv:has_border="true"/>

所有的stdrv属性都是可选的。如果未指定,则使用默认值。

然后创建一个子类STDAdapter的适配器,确保您调用超类构造函数。像这样:

public class SampleAdapter extends STDAdapter<String> {
public SampleAdapter(List<String> versionList) {
    super(versionList);
}

}

接下来,请确保调用该setupSwipeToDelete方法以设置“滑动删除”功能。

mRecyclerView.setupSwipeToDelete(your_adapter_instance, swipe_directions);

swipe_directions 是您允许刷卡物品的方向。

例:

// Get your recycler view from the XML layout
mRecyclerView = (STDRecyclerView) findViewById(R.id.recycler_view);
LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(layoutManager);
mAdapter = new SampleAdapter(versions);
// allow swiping in both directions (left-to-right and right-to-left)
mRecyclerView.setupSwipeToDelete(mAdapter, ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT);

而已!有关更高级的设置(即,为不同的项目设置不同的删除消息,临时和永久删除项目,...),请参阅项目自述页面。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.