android 限制项目在一个范围内拖动 itemtouchhelper

android limit item dragging in a range itemtouchhelper

我用 RecyclerView 显示了一个项目列表,我有不同类型的项目(headers 和项目),如下所示

Header 1
Item 1
Item 2
Header 2
Item 3
Item 4 
Item 5
Item 6
Header 3
Item 7
....

我想限制在 Header 部分内交换项目的位置。因此,例如,项目 4 可以与项目 3、项目 5 和项目 6 交换,但不能超出其部分边界。我正在使用 ItemTouchHelper 来实现拖动机制的交换,如这里所建议的 https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-b9456d2b1aaf and https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-6a6f0c422efd 我重载了 canDropOver 方法,如果您想交换例如项目 4 和 Header 2,这会有所帮助,但不会阻止我将项目拖动到 Header 1。有什么建议吗?

设置 canDropOver 后,最后一块拼图是覆盖 onChildDraw 并限制 dY 值(假设垂直列表 - 限制 dX 值(如果使用水平列表)每当 ViewHolder 被拖向相邻的 ViewHolder 它就不能掉落。

例如:

    override fun onChildDraw(
        c: Canvas,
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        dX: Float,
        dY: Float,
        actionState: Int,
        isCurrentlyActive: Boolean
    ) {
        val previousViewHolder = recyclerView.findViewHolderForAdapterPosition(viewHolder.bindingAdapterPosition - 1)
        val nextViewHolder = recyclerView.findViewHolderForAdapterPosition(viewHolder.bindingAdapterPosition + 1)
        val isDraggingUpward = dY < 0
        val isDraggingDownward = dY > 0

        val isDraggingIntoUndraggableArea =
            (isDraggingUpward && previousViewHolder != null && !canDropOver(recyclerView, viewHolder, previousViewHolder))
            || (isDraggingDownward && nextViewHolder != null && !canDropOver(recyclerView, viewHolder, nextViewHolder))

        val newDy = if (isDraggingIntoUndraggableArea) {
            0f  // Clamp
        } else {
            dY
        }

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

我还有一个存储库,你可以参考它有一个完整的应用程序示例: https://github.com/nihk/ClampedItemTouchHelper