
Pada bagian pertama, kami melihat ItemTouchHelper dan implementasi ItemTouchHelper.Callback , yang menambahkan fungsi drag & drop dan swipe-to-dismiss ke RecyclerView
. Di artikel ini, kami akan melanjutkan apa yang telah dilakukan di sebelumnya dengan menambahkan dukungan untuk mengatur elemen dalam bentuk kisi, drag and drop controller, pemilihan item daftar, dan animasi swipe kustom.

Seret dan lepas pengontrol
Saat membuat daftar yang mendukung drag & drop , mereka biasanya menerapkan kemampuan untuk menarik dan menjatuhkan item dengan sentuhan. Ini berkontribusi pada kejelasan dan kemudahan penggunaan daftar dalam "mode pengeditan", dan juga direkomendasikan oleh pedoman materi. Menambahkan pengontrol seret dan lepas ke contoh kita sangat mudah.

Pertama, perbarui layout
elemen ( item_main.xml ).
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/item" android:layout_width="match_parent" android:layout_height="?listPreferredItemHeight" android:clickable="true" android:focusable="true" android:foreground="?selectableItemBackground"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="16dp" android:textAppearance="?android:attr/textAppearanceMedium" /> <ImageView android:id="@+id/handle" android:layout_width="?listPreferredItemHeight" android:layout_height="match_parent" android:layout_gravity="center_vertical|right" android:scaleType="center" android:src="@drawable/ic_reorder_grey_500_24dp" /> </FrameLayout>
Gambar yang digunakan untuk pengontrol drag dapat ditemukan di ikon Desain Bahan dan ditambahkan ke proyek menggunakan plugin generator ikon yang nyaman di Android Studio.
Seperti yang disebutkan secara singkat di artikel sebelumnya, Anda dapat menggunakan ItemTouchHelper.startDrag(ViewHolder)
untuk memulai tarik dan lepas secara terprogram. Jadi, yang perlu kita lakukan adalah memperbarui ViewHolder
dengan menambahkan pengontrol seret dan mengatur pengendali sentuh sederhana yang akan memanggil startDrag()
.
Kami membutuhkan antarmuka untuk mengirimkan peristiwa di sepanjang rantai:
public interface OnStartDragListener { void onStartDrag(RecyclerView.ViewHolder viewHolder); }
Kemudian tentukan ImageView
untuk pengontrol seret di ItemViewHolder
:
public final ImageView handleView; public ItemViewHolder(View itemView) { super(itemView);
dan perbarui RecyclerListAdapter
:
private final OnStartDragListener mDragStartListener; public RecyclerListAdapter(OnStartDragListener dragStartListener) { mDragStartListener = dragStartListener;
RecyclerListAdapter
sekarang akan terlihat seperti ini .
Yang masih harus dilakukan adalah menambahkan OnStartDragListener
ke fragmen:
public class RecyclerListFragment extends Fragment implements OnStartDragListener {
RecyclerListFragment
sekarang akan terlihat seperti ini . Sekarang, ketika Anda meluncurkan aplikasi, Anda dapat mulai menyeret dan menjatuhkan dengan menyentuh controller.

Menyoroti Item Daftar
Sekarang dalam contoh kita tidak ada indikasi visual dari item yang diseret. Jelas, ini seharusnya tidak, tetapi mudah diperbaiki. Menggunakan ItemTouchHelper
Anda dapat menggunakan efek penyorotan item standar. Pada Lollipop dan versi Android yang lebih baru, lampu latar "menyebar" di atas elemen dalam proses berinteraksi dengannya; pada versi sebelumnya, elemen hanya mengubah warnanya menjadi gelap.
Untuk menerapkan ini dalam contoh kita, cukup tambahkan latar belakang (properti background
) ke root FrameLayout
elemen FrameLayout
atau atur dalam konstruktor RecyclerListAdapter.ItemViewHolder . Akan terlihat seperti ini:

Ini terlihat keren, tetapi Anda mungkin ingin mengontrol lebih banyak lagi. Salah satu cara untuk melakukan ini adalah mengizinkan ViewHolder
menangani perubahan status suatu elemen. Untuk ini, ItemTouchHelper.Callback
menyediakan dua metode lagi:
onSelectedChanged(ViewHolder, int)
dipanggil setiap kali keadaan elemen berubah untuk menyeret ( ACTION_STATE_DRAG ) atau menggesek ( ACTION_STATE_SWIPE ). Ini adalah tempat yang ideal untuk mengubah status komponen view
menjadi aktif .clearView(RecyclerView, ViewHolder)
dipanggil ketika komponen view
seret-dan-jatuhkan selesai, dan juga saat gesek selesai ( ACTION_STATE_IDLE ). Di sini, keadaan awal komponen view
Anda biasanya dipulihkan.
Sekarang, mari kita selesaikan semuanya.
Pertama, buat antarmuka yang akan diimplementasikan oleh ViewHolders
:
public interface ItemTouchHelperViewHolder { void onItemSelected(); void onItemClear(); }
Kemudian, di SimpleItemTouchHelperCallback
terapkan metode yang sesuai:
@Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
Sekarang yang tersisa adalah RecyclerListAdapter.ItemViewHolder
mengimplementasikan ItemTouchHelperViewHolder
:
public class ItemViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
Dalam contoh ini, kami cukup menambahkan latar belakang abu-abu saat elemen aktif, dan kemudian menghapusnya. Jika ItemTouchHelper
dan adaptor Anda terhubung erat, Anda dapat dengan mudah meninggalkan pengaturan ini dan mengganti status komponen view
secara langsung di ItemTouchHelper.Callback
.
Jaring
Jika sekarang Anda mencoba menggunakan GridLayoutManager
, Anda akan melihat bahwa itu tidak berfungsi dengan benar. Alasan dan solusinya sederhana: kita harus memberi tahu ItemTouchHelper
kami bahwa kami ingin mendukung menyeret item ke kiri dan kanan. Sebelumnya di SimpleItemTouchHelperCallback
kita sudah menentukan:
@Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); }
Satu-satunya perubahan yang diperlukan untuk mendukung kisi adalah menambahkan bendera yang sesuai:
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
Namun, swipe-to-dismiss bukanlah perilaku yang sangat alami untuk elemen grid, jadi swipeFlags
kemungkinan besar akan swipeFlags
:
@Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; int swipeFlags = 0; return makeMovementFlags(dragFlags, swipeFlags); }
Untuk melihat contoh GridLayoutManager
berfungsi, lihat RecyclerGridFragment . Begini tampilannya saat startup:

Animasi Geser Khusus
ItemTouchHelper.Callback
menyediakan cara yang sangat nyaman untuk sepenuhnya mengendalikan animasi sambil menyeret atau menyapu. Karena ItemTouchHelper
adalah sebuah RecyclerView.ItemDecoration , kita dapat melakukan intervensi dalam proses rendering komponen tampilan dengan cara yang sama. Pada bagian selanjutnya, kita akan memeriksa pertanyaan ini secara lebih rinci, tetapi untuk sekarang, mari kita lihat contoh sederhana dari menimpa animasi swipe default untuk menunjukkan hilangnya linear.
@Override public void onChildDraw(Canvas c, RecyclerView recyclerView, ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { float width = (float) viewHolder.itemView.getWidth(); float alpha = 1.0f - Math.abs(dX) / width; viewHolder.itemView.setAlpha(alpha); viewHolder.itemView.setTranslationX(dX); } else { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } }
dX
dan dY
adalah pergeseran saat ini relatif terhadap komponen view
dipilih, di mana:
- -1.0f adalah gesekan penuh dari kanan ke kiri (dari
ItemTouchHelper.END
ke ItemTouchHelper.START
) - 1.0f adalah gesekan penuh dari kiri ke kanan (dari
ItemTouchHelper.START
ke ItemTouchHelper.END
)
Penting untuk memanggil super
untuk tindakan apa pun yang tidak Anda proses untuk memicu animasi default.
Pada bagian selanjutnya, kita akan mempertimbangkan contoh di mana kita akan mengontrol gambar elemen pada saat drag and drop.
Kesimpulan
Sebenarnya, pengaturan ItemTouchHelper cukup menyenangkan. Agar tidak menambah volume artikel ini, saya membaginya menjadi beberapa.
Kode sumber
Lihat kode lengkap untuk seri artikel ini di repositori Android-ItemTouchHelper-Demo GitHub. Artikel ini mencakup komit dari ef8f149 hingga d164fba .
← Seret dan Gesek di RecyclerView. Bagian 1: ItemTouchHelper