如何在RecyclerView中使用ItemTouchHelper禁止滑动删除?

15
我使用RecyclerView和ItemTouchHelper进行滑动删除操作,并在滑动的项目下方添加了删除按钮,类似于这样:Swiping spec 但是当我完成滑动后,该项目很快就会从列表中删除!如何锁定滑动的项目,并通过单击删除按钮来删除它?就像Gmail的行为一样。
注:我在此处发布了同样的问题:https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=189057

你成功实现了吗?如果是,请分享RecyclerView的ItemTouchHelper...我卡住了,我已经发布了一个类似于这个问题的问题:http://stackoverflow.com/questions/35131463/swipe-with-recyclerview-without-any-third-party-library - Reprator
5个回答

6
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    float translationX;
    if(dX > 0){
      translationX = Math.min(-dX, viewHolder.itemView.getWidth() / 2);
    }
    else {
       translationX = Math.max(dX, (-1)* viewHolder.itemView.getWidth() / 2);
    }
    super.onChildDraw(c, recyclerView, viewHolder, translationX, dY, actionState, isCurrentlyActive);
}

3
不幸的是,这仅在您打开时有效,当您关闭时需要恢复您收到的dX,直到达到阈值。然后,当您释放时,您会看到物品从中间重新开始,因为真正的dX在中间。 - Davideas

4
只需按照示例“Support7Demos/src/com/example/android/supportv7/widget/touch/SwipeToDismissActivity.java”操作,并在“onChildDraw”方法中进行小修改即可。
public boolean onChildDraw(Canvas c, RecyclerView recyclerView,
        RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
        boolean isCurrentlyActive) {
    float translationX = Math.min(-dX, viewHolder.itemView.getWidth() / 2);
    viewHolder.itemView.setTranslationX(-translationX);
    return true;
}

这个方法必须返回true,否则ItemTouchUIUtil会覆盖translationX。 截图


2

之前提出的解决方案只有最终效果的五分之一。

不幸的是,它们只在您滑动打开1个项目时起作用,但当您关闭它时,您需要恢复从参数接收到的dX金额,直到达到阈值。然后,当您释放时,您会看到该项从中间重新开始,因为您实际接收到的dX仍指向中心!真的很丑陋。

我认为除非有一种方法可以停止接收大于所需宽度的dX,否则您需要解决以下问题:

  • 您需要添加一个复杂的逻辑来发现滑动是指哪个项目。
  • 如果您滚动滑动效果也会丢失。
  • 最后,您无法单击后视图,您需要跟踪该项是否处于滑动位置,如果不保存它,则在单击时,它将以前景视图重新绘制,并且没有动画。

1

在你的SimpleCallback

设置OnClickListeners在你的getMovementFlags()上,然后:

public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    if (dX > ARCHIVE_LAYOUT_WIDTH) {
        getDefaultUIUtil().onDraw(c, recyclerView, ((YOUR_VIEW_HOLDER) viewHolder).getSwipableView(), dX, dY, actionState, isCurrentlyActive);
    }
}

这不是最干净的解决方案,但它会让你更接近目标。


你能帮我解决这个问题吗?https://stackoverflow.com/questions/64385103/swipe-left-and-right-is-not-working-properly 和 https://dev59.com/Yr3pa4cB1Zd3GeqPj7m8 - Vijayadhas Chandrasekaran

0

将 dX 分别除以 2、3、4...,以获取最小值

@Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView,
                            RecyclerView.ViewHolder viewHolder, float dX, float dY,
                            int actionState, boolean isCurrentlyActive) {
        final View foregroundView = ((CreditCardAdapter.ViewHolder) viewHolder).itemView.findViewById(R.id.viewForeground);
        
        super.onChildDraw(c, recyclerView, foregroundView, dX/3, dY,
                actionState, isCurrentlyActive);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接