14

Hi I am using support library android.support.v7.widget.CardView to achieve cardview functionality in my android app. I want to achieve swipe to delete functionality in it as well.

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="200dp"
    android:layout_height="200dp"
    card_view:cardCornerRadius="4dp">

    <TextView
        android:id="@+id/info_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.v7.widget.CardView>

How to achieve swipe to delete functionality in it?

Thanks in advance.

N Sharma
  • 33,489
  • 95
  • 256
  • 444

4 Answers4

30

I adapted romannurik's Android-SwipeToDismiss to do exactly that.

The code is on github with a woking sample application, and consists of:

  • A subclass of RecyclerView.OnItemTouchListener that listens to touch events and detects when an item is being swiped, animating it accordingly.
  • A SwipeListener that is called in order to know if an item can be dismissed and called again when items are dismissed.

To use it, follow the instructions on github, or just copy the class SwipeableRecyclerViewTouchListener to your project and use it like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mItems = new ArrayList<>(30);
    for (int i = 0; i < 30; i++) {
        mItems.add(String.format("Card number %2d", i));
    }

    mAdapter = new CardViewAdapter(mItems);

    mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);

    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    mRecyclerView.setAdapter(mAdapter);

    SwipeableRecyclerViewTouchListener swipeTouchListener =
            new SwipeableRecyclerViewTouchListener(mRecyclerView,
                    new SwipeableRecyclerViewTouchListener.SwipeListener() {
                        @Override
                        public boolean canSwipe(int position) {
                            return true;
                        }

                        @Override
                        public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
                            for (int position : reverseSortedPositions) {
                                mItems.remove(position);
                                mAdapter.notifyItemRemoved(position);
                            }
                            mAdapter.notifyDataSetChanged();
                        }

                        @Override
                        public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
                            for (int position : reverseSortedPositions) {
                                mItems.remove(position);
                                mAdapter.notifyItemRemoved(position);
                            }
                            mAdapter.notifyDataSetChanged();
                        }
                    });

    mRecyclerView.addOnItemTouchListener(swipeTouchListener);
}
brnunes
  • 1,943
  • 26
  • 30
  • How to delete an element? It seems you have no reference to the adapter/element you swipe to remove it. – joninx Jan 12 '15 at 11:47
  • Solved! just call the adapter and remove the element you want within the for loop. – joninx Jan 12 '15 at 12:24
  • Good suggestion! However, this method won't work when the recyclerView is embedded in a SlidingTayLayout. – hackjutsu May 06 '15 at 04:37
  • I don't quite understand one part -- is the `for` loop deleting all items in the adapter or just the one swiped; it seems like the former to me but isn't the latter behaviour more appropriate? Also is it possible to programmatically dismiss the items? If not, how can I adapt your code to do that? (I assume I'd have to do something similar to what `handleTouchEvent` does) – u3l May 30 '15 at 19:39
  • 1
    @uj- The for loop is deleting only the items swiped. If you look at the code (https://github.com/brnunes/SwipeableRecyclerView/blob/master/lib/src/main/java/com/github/brnunes/swipeablerecyclerview/SwipeableRecyclerViewTouchListener.java#L292) executed when an item is being dismissed, you can see that the items are added to a buffer because the dismiss is done only when the animation ends. In my tests I never ran into a case where the array of `reverseSortedPositions` had more than one element, but since that code was part of the original implementation, I left it there. – brnunes Jun 03 '15 at 07:41
  • 1
    @uj- As to how to dismiss an item programmatically, you should be able to add animation when removing an item. This question might help: http://stackoverflow.com/questions/26724964/how-to-animate-recyclerview-items-when-they-appear. Otherwise, you can figure out the location of the item you want to dismiss and simulate a swipe event: http://stackoverflow.com/questions/5867059/android-how-to-create-a-motionevent. – brnunes Jun 03 '15 at 07:54
  • Can I disable the left swipe only? and what can I do If I want a confirmation kind of card showing "undo" after deleting an element like the gmail app!! – P-RAD Jun 12 '15 at 09:55
  • @Dev I've been thinking of adding those functionalities. I'll work on that soon and update the code on github and the answers here. Allowing swipe in only one direction is simple. There's a pull request that I'm going to review soon: https://github.com/brnunes/SwipeableRecyclerView/pull/10. Showing the undo card is a little bit more work. I think we would have to add the undo card instead of removing the swiped item, and then remove the item and the undo card on the next user interaction with the RecyclerView (as gmail does). – brnunes Jun 15 '15 at 18:59
  • 1
    @brnunes exactly I've worked out a part of it . From SwipeableRecyclerView, Change the layout on the first swipe to undo card and removing them on the second swipe. Thanks for the idea – P-RAD Jun 16 '15 at 02:01
9

There is a new approach for swipe delete gesture in android support v7 API. The class name is called ItemTouchHelper.

Mr. Paul Burke wrote an amazing example on how to implement this feature. See this link.

David Arenburg
  • 91,361
  • 17
  • 137
  • 196
Avi Levin
  • 1,868
  • 23
  • 32
0

Adding due to this being the first result.

I was looking for something like this and was having some issues, checked out the first two answers but this was the easiest one I found to implement. Simply stick it in the activity and change the itemlist/adapater/recyclerview to whatever your name is.

ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new 
ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {

        ItemList.remove(viewHolder.getAdapterPosition());
        Adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
    }

    @Override
    public void onMoved(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, int fromPos, RecyclerView.ViewHolder target, int toPos, int x, int y) {
        super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
    }
};

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(RecyclerViewer);

found here: codeproject

lostknight
  • 109
  • 6
0

https://github.com/journaldev/journaldev/tree/master/Android/AndroidRecyclerViewSwipeToDelete gone help you

A subclass of RecyclerView.OnItemTouchListener that listens to touch events and detects when an item is being swiped, animating it accordingly. A SwipeListener that is called in order to know if an item can be dismissed and called again when items are dismissed.