Geser untuk Menutup untuk RecyclerView [ditutup]

116

Saya dulu menggunakan pustaka SwipeToDismiss tetapi sekarang saya mencoba bermigrasi ke RecyclerView dan hal-hal tidak begitu jelas, apakah Anda tahu ada pengganti untuk lib ini? Ada ide bagaimana menerapkannya dari awal?

Viktor Yakunin
sumber
1
Saya telah membuat perpustakaan kecil yang menggunakan ItemTouchHelper untuk membuat pembuatan isyarat untuk recyclerview lebih mudah, Anda dapat menemukannya di sini github.com/olmur/rvtools
Olexii Muraviov

Jawaban:

337

Mulai v22.2.0, tim dukungan Android telah menyertakan ItemTouchHelperkelas yang membuat gesek-untuk-tutup dan seret-dan-lepas menjadi cukup sederhana. Ini mungkin tidak berfitur lengkap seperti beberapa pustaka di luar sana, tetapi berasal langsung dari tim Android.

  • Perbarui build.gradle Anda untuk mengimpor v22.2. + Dari pustaka RecyclerView

    compile 'com.android.support:recyclerview-v7:22.2.+'
  • Buat instance ItemTouchHelper dengan SimpleCallback yang sesuai

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

    ** Perhatikan bahwa SimpleCallback mengambil arah yang Anda inginkan untuk mengaktifkan drag-and-drop dan arah yang Anda inginkan untuk mengaktifkan swiping.

  • Lampirkan ke RecyclerView Anda

    itemTouchHelper.attachToRecyclerView(recyclerView);
jmcdale.dll
sumber
7
Bagaimana seseorang bisa mendapatkan indeks item yang digesek?
MaTTo
37
@Orochi Dengan memanggil getAdapterPosition () di viewHolder.
SqueezyMo
1
Mereka jelas tidak terlalu memikirkan desain komponen ini. Ini hanya berfungsi dengan RecyclerView. Gesek untuk menutup ada untuk hal-hal seperti snackbar. Komponen yang lebih umum yang dapat digunakan dengan tampilan apa pun akan lebih disambut.
AndroidDev
4
Bagaimana jika saya ingin menangani kasus saat pengguna menggeser sebagian tetapi kemudian menyeret tampilan kembali ke posisinya? Rupanya ini tidak mungkin (?) EDIT: ok, itu mungkin, tapi ada sedikit margin yang dapat Anda tetap sebelum tampilan digesek saat rilis. Ada saran?
Matteo
2
@Matteo: Implementasikan ItemTouchHelper.Callback dan timpa getSwipeThreshold ()
Sofi Software LLC
36
 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

Di sini, di Kode jika pengguna menggesek ke kiri maka AlertDialog ditampilkan dan jika pengguna memilih HAPUS maka item dihapus dari database dan recyclerview di-refresh dan jika pengguna memilih BATAL maka recyclerview seperti apa adanya.

Khyati Fatania
sumber
bekerja dengan baik .. jawaban yang bagus.
Sagar Chavada
Hebat! Sangat mudah untuk diterapkan
dianakarenms
1
Anda tidak benar-benar memerlukan pemeriksaan arah if (direction == ItemTouchHelper.LEFT) // if swipe leftkarena ItemTouchHelper.SimpleCallbackdibatasi hanya untuk arah gesek. Jika Anda ingin menggesek ke kiri dan kanan ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)lalu Anda perlu memeriksa arahnya.
Jacko
1
Saya menemukan bahwa mengklik di luar AlertDialog membatalkan dialog tetapi tidak meletakkan item yang saya gesek kembali. Anda dapat merekam ini dengan menambahkan OnCancelListener ke BuilderAlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // stuff to put the item back } });
Jacko
1
+1 Bekerja dengan baik. Saya menemukan adapter.notifyItemChanged(position);membawa kembali item yang digesek, bukan notifyItemRemoved- yang lebih logis imho.
winwaed
14

mungkin Anda bisa mencoba perpustakaan ini:

https://github.com/daimajia/AndroidSwipeLayout

Pembaruan: Saya baru saja menemukan pustaka bagus lainnya yang dapat Anda gunakan dengan RecyclerView:

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

Pierpaolo Paolini
sumber
Saya membuat implementasi saya sendiri mirip dengan github.com/krossovochkin/Android-SwipeToDismiss-RecyclerView . Satu-satunya persyaratan adalah menampilkan Toast dengan tombol "Urungkan", yang tidak tercakup dalam lib Anda.
Viktor Yakunin
1
Pustaka dari Daimajia tidak mendukung fitur gesek untuk menutup.
akohout
@raveN Saya baru saja memperbarui jawaban saya.
Pierpaolo Paolini
2

Perpustakaan ini mungkin helpful.You dapat menerapkan undodi OnDissmissgunakansupertoast

xcodebuild
sumber
Hei, saya akan mencobanya! Apakah berdasarkan jawaban Pierpaolo?
Boy
Ini hanya OnTouchListener menginspirasi oleh ini
xcodebuild
2

Saya menulis pustaka SwipeToDeleteRV yang mendukung fitur swipe-to-delete-undo pada tampilan recycler. Ini didasarkan pada ItemTouchHelper dan sangat mudah digunakan.

Semoga bermanfaat bagi seseorang yang menghadapi masalah yang sama.

Sebagai contoh, Anda bisa menentukan tampilan recycler Anda dalam layout XML seperti biasa, ditambah beberapa atribut opsional:

...
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"/>

Semua atribut stdrv bersifat opsional. Jika Anda tidak menentukannya, yang default akan digunakan.

Kemudian buat adaptor yang mensubkelas STDAdapter, pastikan Anda memanggil konstruktor kelas super. Sesuatu seperti ini:

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

}

Selanjutnya, pastikan Anda melakukan panggilan ke setupSwipeToDeletemetode untuk mengatur fitur geser-untuk-hapus.

mRecyclerView.setupSwipeToDelete(your_adapter_instance, swipe_directions);

swipe_directions adalah arah yang Anda izinkan untuk menggesek item.

Contoh:

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

Itu dia! Untuk pengaturan lebih lanjut (yaitu, mengatur pesan penghapusan yang berbeda untuk item yang berbeda, menghapus item untuk sementara dan selamanya, ...) silakan merujuk ke halaman readme proyek.

H.Nguyen
sumber