
Melanjutkan artikel sebelumnya , dalam artikel ini saya akan berbicara tentang ItemDecoration
dan ItemAnimator
dan mencoba menjelaskan prinsip pekerjaan mereka di RecyclerView
menggunakan contoh aplikasi sederhana yang tersedia di Github .
1. ItemDecoration
ItemDecoration
digunakan untuk menghias item daftar di RecyclerView
.
Dengan ItemDecoration
Anda dapat menambahkan pembagi antara komponen view
, menyelaraskannya, atau membaginya pada interval yang sama. Untuk menambahkan pemisah sederhana antara komponen view
, gunakan kelas DividerItemDecoration
, yang dapat ditemukan di pustaka dukungan versi 25.1.0 dan lebih tinggi. Fragmen kode berikut menunjukkan implementasinya:
mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), mLayoutManager.getOrientation()); recyclerView.addItemDecoration(mDividerItemDecoration);
Cara terbaik untuk membuat pemisah Anda sendiri adalah dengan memperluas kelas RecyclerView.ItemDecoration
. Dalam aplikasi sampel, saya menggunakan GridLayoutManager
dan menerapkan CharacterItemDecoration
ke RecyclerView
:
recyclerView.addItemDecoration(new CharacterItemDecoration(50));
Di sini CharacterItemDecoration
mengatur offset ( eng. Offset) menjadi 50 piksel dalam konstruktornya dan menimpa getItemOffsets(...)
. Di dalam metode getItemOffsets()
, setiap bidang outRects
menentukan jumlah piksel yang harus ditetapkan untuk setiap komponen view
, mirip dengan lekukan dan lekukan. Karena saya menggunakan GridLayoutManager
dan ingin mengatur jarak yang sama antara elemen grid, saya mengatur indentasi di sebelah kanan menjadi 25 piksel (mis. Offset / 2) untuk setiap elemen genap dan indentasi di sebelah kiri hingga 25 piksel untuk setiap elemen aneh, sambil menjaga indentasi atas tetap sama untuk semua elemen.

2. ItemAnimator
ItemAnimator
digunakan untuk menghidupkan elemen atau view
komponen di dalam RecyclerView
.

Mari kita buat aplikasi kita seperti Instagram dengan memperluas DefaultItemAnimator
dan mengganti beberapa metode.
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { return true; }
Metode canReuseUpdatedViewHolder(...)
menentukan apakah ViewHolder
sama ViewHolder
digunakan untuk animasi jika data elemen ini berubah. Jika mengembalikan false
, maka kedua ViewHolders
- lama dan diperbarui - diteruskan ke metode animateChange(...)
.
public ItemHolderInfo recordPreLayoutInformation(@NonNull RecyclerView.State state, @NonNull RecyclerView.ViewHolder viewHolder, int changeFlags, @NonNull List<Object> payloads) { if (changeFlags == FLAG_CHANGED) { for (Object payload : payloads) { if (payload instanceof String) { return new CharacterItemHolderInfo((String) payload); } } } return super.recordPreLayoutInformation(state, viewHolder, changeFlags, payloads); } public static class CharacterItemHolderInfo extends ItemHolderInfo { public String updateAction; public CharacterItemHolderInfo(String updateAction) { this.updateAction = updateAction; } }
RecyclerView
memanggil metode recordPreLayoutInformation(...)
untuk memulai rendering layout
. ItemAnimator
harus mencatat informasi yang diperlukan tentang komponen view
sebelum ditimpa, dipindahkan, atau dihapus. Data yang dikembalikan oleh metode ini akan ditransfer ke metode animasi yang sesuai (dalam kasus kami, ini adalah animateChange(...)
).
@Override public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) { if (preInfo instanceof CharacterItemHolderInfo) { CharacterItemHolderInfo recipesItemHolderInfo = (CharacterItemHolderInfo) preInfo; CharacterRVAdapter.CharacterViewHolder holder = (CharacterRVAdapter.CharacterViewHolder) newHolder; if (CharacterRVAdapter.ACTION_LIKE_IMAGE_DOUBLE_CLICKED.equals(recipesItemHolderInfo.updateAction)) { animatePhotoLike(holder); } } return false; } private void animatePhotoLike(final CharacterRVAdapter.CharacterViewHolder holder) { holder.likeIV.setVisibility(View.VISIBLE); holder.likeIV.setScaleY(0.0f); holder.likeIV.setScaleX(0.0f); AnimatorSet animatorSet = new AnimatorSet(); ObjectAnimator scaleLikeIcon = ObjectAnimator.ofPropertyValuesHolder (holder.likeIV, PropertyValuesHolder.ofFloat("scaleX", 0.0f, 2.0f), PropertyValuesHolder.ofFloat("scaleY", 0.0f, 2.0f), PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f, 0.0f)); scaleLikeIcon.setInterpolator(DECELERATE_INTERPOLATOR); scaleLikeIcon.setDuration(1000); ObjectAnimator scaleLikeBackground = ObjectAnimator.ofPropertyValuesHolder (holder.characterCV, PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.95f, 1.0f), PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.95f, 1.0f)); scaleLikeBackground.setInterpolator(DECELERATE_INTERPOLATOR); scaleLikeBackground.setDuration(600); animatorSet.playTogether(scaleLikeIcon, scaleLikeBackground); animatorSet.start(); }
RecyclerView
memanggil metode animateChange(...)
ketika elemen adaptor ada sebelum dan setelah rendering setelah memanggil metode notifyItemChanged(int)
. Metode ini juga dapat digunakan saat memanggil notifyDataSetChanged()
, jika adaptor menggunakan pengidentifikasi stabil. Ini diperlukan agar RecyclerView
dapat menggunakan kembali komponen view
dalam ViewHolders
sama. Perhatikan bahwa metode ini menggunakan argumen: (ViewHolder oldHolder, ViewHolder newHolder, ItemHolderInfo preInfo, ItemHolderInfo postInfo) . Karena kami menggunakan kembali ViewHolder
, oldHolder dan newHolder adalah sama.
Setiap kali pengguna mengklik dua kali pada item apa pun, metode berikut ini disebut:
notifyItemChanged(position, ACTION_LIKE_IMAGE_DOUBLE_CLICKED);
Ini memulai seluruh rangkaian panggilan: canReuseUpdatedViewHolder(...)
, recordPreLayoutInformation(...)
dan, akhirnya, animateChange(...)
di ItemAnimator
, yang, pada gilirannya, menggerakkan item daftar dan ikon hati di elemen ini ( contoh di GIF di atas).
Ini adalah bagian kedua dari serangkaian artikel tentang RecyclerView
. Jika Anda melewatkan bagian pertama, baca di sini .
Beberapa artikel bagus tentang RecyclerView
:
← Kiat untuk penggunaan profesional RecyclerView. Bagian 1