📌  相关文章
📜  在Android RecyclerView中滑动以删除和撤消(1)

📅  最后修改于: 2023-12-03 15:07:51.753000             🧑  作者: Mango

在Android RecyclerView中滑动以删除和撤消

RecyclerView是一个非常有用的Android控件,它允许开发人员更容易地管理大型数据集,并提供了灵活的方式来处理用户交互。其中之一是允许用户通过触摸屏幕滑动来删除特定项以及撤消这些操作。

删除项

要在RecyclerView中删除项,您需要实现以下步骤:

  1. 创建一个RecyclerView.Adapter,它将显示要删除的数据项。
  2. 为RecyclerView设置ItemTouchHelper.Callback,以便用户可以以滑动的方式删除项。
  3. 实现RecyclerView.ViewHolder以及onBindViewHolder方法以显示要删除的数据项。
  4. 实现onItemDismiss方法来删除数据项。

以下是一个基本的示例:

首先,我们需要创建一个RecyclerView.Adapter:

class MyAdapter(private val dataList: MutableList<String>) :
    RecyclerView.Adapter<MyAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view =
            LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val data = dataList[position]
        holder.data.text = data
    }

    override fun getItemCount() = dataList.size

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val data: TextView = itemView.findViewById(R.id.data)
    }

    fun removeItem(position: Int) {
        dataList.removeAt(position)
        notifyItemRemoved(position)
    }
}

接下来,我们需要设置ItemTouchHelper.Callback,以便用户可以滑动以删除项:

class SwipeToDeleteCallback(private val adapter: MyAdapter) :
    ItemTouchHelper.Callback() {

    override fun getMovementFlags(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder
    ): Int {
        val dragFlags = 0
        val swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
        return makeMovementFlags(dragFlags, swipeFlags)
    }

    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        return false
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        adapter.removeItem(viewHolder.adapterPosition)
    }
}

现在我们需要实现ViewHolder和onBindViewHolder方法,以显示要删除的数据项:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val view =
        LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
    return ViewHolder(view)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val data = dataList[position]
    holder.data.text = data
}

最后,我们需要实现onItemDismiss方法来删除数据项:

fun removeItem(position: Int) {
    dataList.removeAt(position)
    notifyItemRemoved(position)
}

现在,当用户向左或向右滑动以删除项时,我们的RecyclerView将调用onItemDismiss方法,该方法将从数据列表中删除该项并更新RecyclerView。

撤销删除

要允许撤消在RecyclerView中的删除操作,您需要实现以下步骤:

  1. 创建一个Snackbar,允许用户撤消其删除操作。
  2. 在onItemDismiss方法中,在recyclerView.adapter.itemCount中添加删除后的itemCount以获得正确的snackbar高度。
  3. 存储删除项的位置,以便在Snackbar的撤消操作中还原它。

以下是一个基本的示例:

首先,我们需要在onItemDismiss方法中添加用于启动Snackbar的代码:

override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
    val position = viewHolder.adapterPosition
    val data = adapter.dataList[position]

    adapter.removeItem(position)

    val snackbar = Snackbar
        .make(
            recyclerView,
            "Item deleted",
            Snackbar.LENGTH_LONG
        )
        .setAction("UNDO") {
            adapter.undoDelete(position, data)
        }

    snackbar.duration = 5000
    snackbar.show()
}

然后,我们需要实现undoDelete方法:

fun undoDelete(position: Int, data: String) {
    dataList.add(position, data)
    notifyItemInserted(position)
}

最后,我们需要存储删除的项的位置:

fun removeItem(position: Int) {
    val data = dataList[position]

    dataList.removeAt(position)
    notifyItemRemoved(position)

    deletedItems.add(DeletedItem(position, data))
}

fun undoDelete(position: Int, data: String) {
    dataList.add(position, data)
    notifyItemInserted(position)

    deletedItems.removeAll { it.position == position }
}

现在,当用户滑动以删除项时,我们的RecyclerView将启动一个Snackbar,允许用户撤消该删除操作。如果用户选择取消,我们将在RecyclerView中还原该项。

注意事项

请注意,在使用RecyclerView和ItemTouchHelper.Callback时,您需要明确以下几点:

  1. 移动操作可以被禁用:
val dragFlags = 0
val swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
return makeMovementFlags(dragFlags, swipeFlags)
  1. 从RecyclerView中删除项时,您也必须从数据列表中删除该项:
fun removeItem(position: Int) {
    dataList.removeAt(position)
    notifyItemRemoved(position)
}
  1. 当启动Snackbar以撤消删除操作时,您也必须从已删除项列表中删除该项:
fun undoDelete(position: Int, data: String) {
    dataList.add(position, data)
    notifyItemInserted(position)

    deletedItems.removeAll { it.position == position }
}

综上所述,使用RecyclerView管理大量数据并在其中启用交互操作是一项极好的工作。通过实现ItemTouchHelper.Callback和Snackbar,您可以让用户轻松地滑动以删除和撤消操作。