15
votes

I use RecyclerView with ItemTouchHelper to do swiping to remove, and add delete button under the swipe item like this: Swiping spec

But when I finish swiping, the item will be removed from the list soon! How can I lock the swiped item, and removed by clicking the delete button? Just like Gmail's behavior.

ps. I post same issues here 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

5
had u able to achieve it..if yes please share the ItemTouchHelper of recyclerview...i am stuck, i had posted a question similar to this, stackoverflow.com/questions/35131463/…Reprator

5 Answers

5
votes
@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);
}
4
votes

Just follow the example "Support7Demos/src/com/example/android/supportv7/widget/touch/SwipeToDismissActivity.java", and make a small change in method "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;
}

This method must return true, otherwise ItemTouchUIUtil would override the translationX Screenshot

2
votes

The solutions proposed before this post make only 1/5 of the final effect.

Unfortunately, they work only when you swipe to open 1 item, but when you close it you need to recover the amount of dX you receive from the parameter until you reach the threshold. Then, when you release you see the item starting from the middle again because the real dX you receive is still pointing to the middle! Really ugly glitch.

I believe The ItemTouchHelper works only for fully swiping 1 item per time. Unless there's a way to stop receiving the dX that is bigger than the desired width, then you need to resolve the following issue:

  • You need to add a complex logic to discover for which item the swiping is referring to.
  • If you scroll the swipe effect is lost as well.
  • Finally, you can't click the rear view, you need to keep track that the item is in swiped position, if you don't save it, as soon as you click, it redraws with the front view and without animation.
1
votes

On your SimpleCallback

Set OnClickListeners on your getMovementFlags() and then:

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);
    }
}

This isn't the most clean solution but it will get you closer.

0
votes

Divide dX by 2, 3, 4 ... to swipe minimum

@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);
    }