RecyclerView ItemTouchHelper.Callback:拖动交换条件

vad*_*ole 6 java android drag-and-drop android-recyclerview itemtouchhelper

我想实现拖动卡片的方式,当我拖动的卡片没有完全重叠元素时,卡片的重新排列开始,但只有 50%。

看看一个例子:

例子

现在,为了让右边的卡片向左移动,我需要将它与我正在拖动的卡片完全重叠。

我尝试从 ItemTouchHelper.Callback 覆盖此方法:

 public float getMoveThreshold(@NonNull ViewHolder viewHolder) {
     return .5f;
 }
Run Code Online (Sandbox Code Playgroud)

但它没有帮助。

那么我怎样才能让交换发生在 50% 而不是 100% 重叠?

vad*_*ole 2

经过多次尝试,我自己找到了解决方案:

\n

例子

\n

您需要重写 ItemTouchHelper.Callback 中的 ChooseDropTarget 方法。

\n

我就是这样做的:

\n
  //  x \xe2\x89\xa5 0.5 (if less than 0.5, it will shake due to constant overlap)\nval DRAG_THRESHOLD_PERSENT = 0.5\noverride fun chooseDropTarget(\n    selected: ViewHolder,\n    targets: MutableList<ViewHolder>,\n    curX: Int, curY: Int\n): ViewHolder? {\n    val verticalOffset = (selected.itemView.height * DRAG_THRESHOLD_PERSENT).toInt()\n    val horizontalOffset = (selected.itemView.width * DRAG_THRESHOLD_PERSENT).toInt()\n    val left = curX - horizontalOffset\n    val right = curX + selected.itemView.width + horizontalOffset\n    val top = curY - verticalOffset\n    val bottom = curY + selected.itemView.height + verticalOffset\n    var winner: ViewHolder? = null\n    var winnerScore = -1\n    val dx = curX - selected.itemView.left\n    val dy = curY - selected.itemView.top\n    val targetsSize = targets.size\n    for (i in 0 until targetsSize) {\n        val target = targets[i]\n        if (dx > 0) {\n            val diff = target.itemView.right - right\n            if (diff < 0 && target.itemView.right > selected.itemView.right) {\n                val score = abs(diff)\n                if (score > winnerScore) {\n                    winnerScore = score\n                    winner = target\n                }\n            }\n        }\n        if (dx < 0) {\n            val diff = target.itemView.left - left\n            if (diff > 0 && target.itemView.left < selected.itemView.left) {\n                val score = abs(diff)\n                if (score > winnerScore) {\n                    winnerScore = score\n                    winner = target\n                }\n            }\n        }\n        if (dy < 0) {\n            val diff = target.itemView.top - top\n            if (diff > 0 && target.itemView.top < selected.itemView.top) {\n                val score = abs(diff)\n                if (score > winnerScore) {\n                    winnerScore = score\n                    winner = target\n                }\n            }\n        }\n        if (dy > 0) {\n            val diff = target.itemView.bottom - bottom\n            if (diff < 0 && target.itemView.bottom > selected.itemView.bottom) {\n                val score = abs(diff)\n                if (score > winnerScore) {\n                    winnerScore = score\n                    winner = target\n                }\n            }\n        }\n    }\n    return winner\n}\n
Run Code Online (Sandbox Code Playgroud)\n

工作原理:
\n我正在使用因子和宽度/高度计算所选视图的偏移量。之后,我创建新的边框(左、右、上、下),向所选视图的边框添加偏移量,然后在方法中使用它们而不是原始边框

\n

重要的:

\n
    \n
  • 你不应该调用 super
  • \n
  • 系数必须大于0.5
  • \n
\n