我有一个带有ItemTouchHelper的回收者视图。 它允许拖动项目。
我想将拖动限制在回收者视图的范围内 - 即您只能将视图拖到容器外部,以便它消失。
我试着像这样检查绝对坐标:
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
recyclerView.getLocationOnScreen(pos);
int rvY = pos[1];
viewHolder.itemView.getLocationOnScreen(pos);
int vhY = pos[1];
if (rvY > vhY || rvY + recyclerView.getHeight() < vhY + viewHolder.itemView.getHeight()) {
return;
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
...
}
然后我遇到了有点渲染的可靠性 - 如果我慢慢地移动视图,它会在越界时停止移动,但如果我移动速度更快 - 那么无论如何它都会离开循环器视图边界。
任何想法/方法?
答案 0 :(得分:4)
必须将dY值剪裁到回收器视图边界:
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
{
float topY = viewHolder.itemView.getTop() + dY;
float bottomY = topY + viewHolder.itemView.getHeight();
if (topY < 0)
{
dY = 0;
}
else if (bottomY > recyclerView.getHeight())
{
dY = recyclerView.getHeight() - viewHolder.itemView.getHeight() - viewHolder.itemView.getTop();
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
答案 1 :(得分:0)
我调整了user1185087的答案,这样,如果拖动确实消失了,它就不会搬运您的物品,而只会搬运它。
@Override
public void onChildDraw(@NotNull Canvas c, @NotNull RecyclerView recyclerView,
@NotNull RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
float topY = viewHolder.itemView.getTop() + dY;
float bottomY = topY + viewHolder.itemView.getHeight();
// Only redraw child if it is inbounds of view
if (topY > 0 && bottomY < recyclerView.getHeight()){
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
答案 2 :(得分:0)
我有同样的问题。所有的答案都帮助我找到了没有滞后的更好方法。 :)
如果仅使用 dY ,则会产生滞后。因此,我在 onChildDraw 中为itemView添加位置确定。
override fun onChildDraw(c: Canvas, recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float,
actionState: Int, isCurrentlyActive: Boolean) {
var edgeY = dY
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
val lastPosition = (recyclerView.adapter?.itemCount ?: 0) - 1
val view = viewHolder.itemView
val pieceHeight = view.height / PIECE_RATIO
val topEdge = recyclerView.top - pieceHeight
val bottomEdge = recyclerView.height - view.bottom + pieceHeight
if (movePosition == 0 && dY < topEdge) {
edgeY = topEdge
} else if (movePosition == lastPosition && dY > bottomEdge) {
edgeY = bottomEdge
}
}
super.onChildDraw(c, recyclerView, viewHolder, dX, edgeY, actionState, isCurrentlyActive)
}
此代码:
/**
* Variable need for best performance and more productive, because
* get [RecyclerView.ViewHolder.getAdapterPosition] inside [onChildDraw]
* is hard calculating operation
*/
protected var movePosition = RecyclerView.NO_POSITION
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
/**
* Get position on drag start
*/
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
movePosition = viewHolder?.adapterPosition ?: RecyclerView.NO_POSITION
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
/**
* Clear position on drag end
*/
movePosition = RecyclerView.NO_POSITION
}
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder): Boolean {
/**
* Get position on drag
*/
movePosition = target.adapterPosition
return false
}
子类可以这样使用 movePosition :
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder): Boolean {
super.onMove(recyclerView, viewHolder, target)
return callback.onTouchMove(viewHolder.adapterPosition, movePosition)
}
您可以在以下链接中找到所有源代码和示例:github project