Swipe to Dismiss for RecyclerView [closed]
Asked Answered
A

5

119

I used to SwipeToDismiss library but now I'm trying to migrate to RecyclerView and things are not so obvious, do you know any replacements for this lib? Any ideas how to implement it from the scratch?

Arguseyed answered 4/12, 2014 at 12:20 Comment(1)
I have made small library which use ItemTouchHelper to make gestures creation for recyclerview easier, you can find it here github.com/olmur/rvtoolsStagg
B
341

As of v22.2.0, the Android support team has included an ItemTouchHelper class that makes swipe-to-dismiss and drag-and-drop pretty simple. This may not be as full-featured as some of the libraries out there, but it comes directly from the Android team.

  • Update your build.gradle to import v22.2.+ of the RecyclerView library

    compile 'com.android.support:recyclerview-v7:22.2.+'
    
  • Instantiate an ItemTouchHelper with an appropriate SimpleCallback

    ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
        [...]
        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
            //Remove swiped item from list and notify the RecyclerView
        }
    };
    
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
    

    ** Note that the SimpleCallback takes in the directions that you want to enable drag-and-drop and the directions that you want to enable swiping.

  • Attach to your RecyclerView

    itemTouchHelper.attachToRecyclerView(recyclerView);
    
Beatrice answered 2/6, 2015 at 16:27 Comment(11)
How can one get index of swiped item?Lagas
@Orochi By calling getAdapterPosition() on the viewHolder.Maloriemalory
Hi guys! And how do I reach the getAdapterPosition() from the Activity? The viewHolder is on my Adapter and I don't know how to get the View position that I'm swipping from the ItemTouchHelper. Did I must to do that on Adapter's holder? How? PS: Feel free to ask to move this as a new question.Alisonalissa
Nevermind, I found the viewHolder reference when the onSwipe() is called. Thank you!.Alisonalissa
Remember to user UP/DOWN if you have a horizontal list :)Tigerish
They clearly didn't put too much thought into the design of this component. It only works with a RecyclerView. Swipe-to-dismiss exists for things like snackbars. A more generic component that could be used with any view would have been more welcomed.Hustle
What if I want to handle the case when the user swipe partially but then drag the view back in position? Apparently this is not possibile(?) EDIT: ok, it IS possibile, but there's a very little margin which you can stay in before the view get swiped on release. Any suggestion?Aduwa
@Matteo: Implement ItemTouchHelper.Callback and override getSwipeThreshold()Kreegar
For me the following blog post with provided example application on git was very helpful. I recommend you to go through it. It is demonstrating implementation of swiping items in RecyclerView also with the Undo functionality and background colored hints. RecyclerView “swipe to delete”. No 3rd party lib necessaryArlindaarline
I have made small library which use ItemTouchHelper to make gestures creation easier, you can find it here github.com/olmur/rvtoolsStagg
I try out you solution but I have a crash :#45099395Nappe
S
37
 ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            return false;
        }

        @Override
        public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
            final int position = viewHolder.getAdapterPosition(); //get position which is swipe

            if (direction == ItemTouchHelper.LEFT) {    //if swipe left

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); //alert for confirm to delete
                builder.setMessage("Are you sure to delete?");    //set message

                builder.setPositiveButton("REMOVE", new DialogInterface.OnClickListener() { //when click on DELETE
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        adapter.notifyItemRemoved(position);    //item removed from recylcerview
                        sqldatabase.execSQL("delete from " + TABLE_NAME + " where _id='" + (position + 1) + "'"); //query for delete
                        list.remove(position);  //then remove item

                        return;
                    }
                }).setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {  //not removing items if cancel is done
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        adapter.notifyItemRemoved(position + 1);    //notifies the RecyclerView Adapter that data in adapter has been removed at a particular position.
                        adapter.notifyItemRangeChanged(position, adapter.getItemCount());   //notifies the RecyclerView Adapter that positions of element in adapter has been changed from position(removed element index to end of list), please update it.
                        return;
                    }
                }).show();  //show alert dialog
            }
        }
    };
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
    itemTouchHelper.attachToRecyclerView(recyclerView); //set swipe to recylcerview

Here in Code if user swipe left then AlertDialog is displayed and if user select REMOVE then item is deleted from database and recyclerview is refreshed and if user select CANCEL then recyclerview is as it is.

Scalise answered 19/1, 2017 at 11:44 Comment(12)
working good.. nice answer.Anastigmatic
Awesome! So easy to implementHescock
Why are you calling notifyItemRemoved in onCancel?Traceetracer
adapter.notifyItemRemoved(position + 1); will get back item that is swiped if user select CANCEL (means don't want to delete item)Scalise
You don't really need the direction check if (direction == ItemTouchHelper.LEFT) // if swipe left as the ItemTouchHelper.SimpleCallback is limited to just that swipe direction. If you want left and right swipes then ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) and then you would need to check the direction.Detailed
I found that clicking outside the AlertDialog canceled the dialog but did not put the item I swiped back. You can capture this adding an OnCancelListener to the Builder AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // stuff to put the item back } });Detailed
Brilliant!! This works great.Bodiless
+1 Works well. I found adapter.notifyItemChanged(position); brought the swiped item back, rather than notifyItemRemoved - which is more logical imho.Bold
doesn't work, app crashesMulloy
works exactly same as i want. you can also include delete api call in alert dialog positive button click.. nicePhoton
This answer is helpful for laying out how to make it happen, but there is a HUGE problem with it. Determining the ID in your database by the position on your list is a mistake. Why? For one, once you delete a single row, it no longer works. This all assumes all the IDs are exactly matched up to the rows in the first place. It also doesn't work if your data is sorted by some other field or moved around or really anything. Just want to make sure people realize that when reading this answer. It's kind of a big deal. I did leverage this answer to set mine up correctly though.Scotland
working fine but when i tried to delete last item and click the cancel button that(last item of list ) is goneBrott
D
15

maybe you could try this library:

https://github.com/daimajia/AndroidSwipeLayout

Update: I've just found another good library that you can use with RecyclerView:

https://github.com/hudomju/android-swipe-to-dismiss-undo

Depersonalize answered 25/2, 2015 at 14:17 Comment(3)
I made my own implementation similar to github.com/krossovochkin/Android-SwipeToDismiss-RecyclerView. The only requirement was to show Toast with "Undo" button, wich is not covered in your lib.Arguseyed
The library from Daimajia does not support the swipe-to-dismiss feature.Reinaldoreinaldos
@raveN i've just updated my answer.Depersonalize
C
2

This library may be helpful.You can implement undo in OnDissmiss use supertoast

Casket answered 5/5, 2015 at 0:24 Comment(2)
Hey, I'm going to give it a try! Is it based on the one answered by Pierpaolo?Kwei
It's just a OnTouchListener inspire by thisCasket
A
2

I wrote SwipeToDeleteRV library which supports swipe-to-delete-undo feature on recycler views. It is based on ItemTouchHelper and very easy to use.

Hope it may be helpful for someone facing the same issues.

As an example, you can define your recycler view in an XML layout as normal, plus some optional attributes:

...
xmlns:stdrv="http://schemas.android.com/apk/res-auto"
...
<io.huannguyen.swipetodeleterv.STDRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
stdrv:border_color="@android:color/darker_gray" // specify things like border color, border width, etc.
stdrv:delete_view_background="#cccccc"
stdrv:delete_icon="@drawable/ic_archive"
stdrv:delete_icon_height="24dp"
stdrv:delete_icon_width="24dp"
stdrv:left_delete_icon_margin="32dp"
stdrv:delete_message="@string/delete_message"
stdrv:right_delete_icon_margin="32dp"
stdrv:delete_icon_color="#000000"
stdrv:has_border="true"/>

All stdrv attributes are optional. If you don't specify them, the default ones would be used.

Then create an adapter that subclasses STDAdapter, make sure you call the super class constructor. Something like this:

public class SampleAdapter extends STDAdapter<String> {
public SampleAdapter(List<String> versionList) {
    super(versionList);
}

}

Next make sure you make a call to the setupSwipeToDelete method to set the swipe-to-delete feature up.

mRecyclerView.setupSwipeToDelete(your_adapter_instance, swipe_directions);

swipe_directions is the direction you allow items to be swiped.

Example:

// Get your recycler view from the XML layout
mRecyclerView = (STDRecyclerView) findViewById(R.id.recycler_view);
LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(layoutManager);
mAdapter = new SampleAdapter(versions);
// allow swiping in both directions (left-to-right and right-to-left)
mRecyclerView.setupSwipeToDelete(mAdapter, ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT);

That's it! For more advanced settings (i.e., set different deletion messages for different items, temporarily and permanently remove items,...) please refer to the project readme page.

Amal answered 14/6, 2016 at 3:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.