【问题标题】:Swipe to Dismiss for RecyclerView [closed]滑动以关闭 RecyclerView [关闭]
【发布时间】:2014-12-04 12:20:06
【问题描述】:

我曾经使用过SwipeToDismiss 库,但现在我正在尝试迁移到 RecyclerView,但事情并不那么明显,你知道这个库的替代品吗?任何想法如何从头开始实现它?

【问题讨论】:

  • 我制作了一个小库,它使用 ItemTouchHelper 使 recyclerview 的手势创建更容易,你可以在这里找到它 github.com/olmur/rvtools

标签: android android-recyclerview


【解决方案1】:

从 v22.2.0 开始,Android 支持团队包含一个 ItemTouchHelper 类,它使滑动关闭和拖放变得非常简单。这可能不像现有的某些库那样功能齐全,但它直接来自 Android 团队。

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

    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);
    

【讨论】:

  • 如何获取被刷项目的索引?
  • @Orochi 通过在viewHolder 上调用getAdapterPosition()
  • 他们显然没有在这个组件的设计上考虑太多。它仅适用于 RecyclerView。小吃店之类的东西存在滑动解雇。可以与任何视图一起使用的更通用的组件会更受欢迎。
  • 如果我想处理用户部分滑动但又将视图拖回原位的情况怎么办?显然这不是可能的(?)编辑:好的,它是可能的,但是在视图在发布时被刷卡之前,您可以保留很小的余量。有什么建议吗?
  • @Matteo:实现 ItemTouchHelper.Callback 并覆盖 getSwipeThreshold()
【解决方案2】:
 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 保持原样。

【讨论】:

  • 工作得很好。很好的答案。
  • 太棒了!很容易实现
  • 您并不真正需要方向检查if (direction == ItemTouchHelper.LEFT) // if swipe left,因为ItemTouchHelper.SimpleCallback 仅限于该滑动方向。如果你想要左右滑动然后ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) 然后你需要检查方向。
  • 我发现在 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 } });
  • +1 效果很好。我发现 adapter.notifyItemChanged(position); 把刷过的物品带回来了,而不是 notifyItemRemoved - 这是更合乎逻辑的恕我直言。
【解决方案3】:

也许你可以试试这个库:

https://github.com/daimajia/AndroidSwipeLayout

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

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

【讨论】:

【解决方案4】:

This library 可能会有所帮助。您可以在OnDissmiss 中实现undo 使用supertoast

【讨论】:

  • 嘿,我要试一试!是根据 Pierpaolo 的回答吗?
  • 这只是OnTouchListenerthis 的启发
【解决方案5】:

我写了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);

就是这样!更高级的设置(例如,为不同的项目设置不同的删除消息,临时和永久删除项目,...)请参考项目自述页面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-17
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多