Bagaimana seseorang menyegarkan data yang ditampilkan di RecyclerView
(memanggil notifyDataSetChanged
adaptornya) dan memastikan bahwa posisi gulir diatur ulang ke tempat yang tepat?
Dalam kasus yang baik ListView
semua yang diperlukan adalah mengambil getChildAt(0)
, memeriksa getTop()
dan memanggil setSelectionFromTop
dengan data yang persis sama sesudahnya.
Sepertinya tidak mungkin dalam kasus RecyclerView
.
Saya kira saya seharusnya menggunakan its LayoutManager
yang memang menyediakan scrollToPositionWithOffset(int position, int offset)
, tapi apa cara yang tepat untuk mengambil posisi dan offsetnya?
layoutManager.findFirstVisibleItemPosition()
dan layoutManager.getChildAt(0).getTop()
?
Atau adakah cara yang lebih elegan untuk menyelesaikan pekerjaan?
sumber
Jawaban:
Saya menggunakan yang ini. ^ _ ^
Ini lebih sederhana, semoga bisa membantu Anda!
sumber
Saya memiliki masalah yang sangat mirip. Dan saya datang dengan solusi berikut.
Menggunakan
notifyDataSetChanged
adalah ide yang buruk. Anda harus lebih spesifik, kemudianRecyclerView
akan menyimpan status gulir untuk Anda.Misalnya, jika Anda hanya perlu menyegarkan, atau dengan kata lain, Anda ingin setiap tampilan di-rebind, cukup lakukan ini:
sumber
notifyDataSetChanged
posisi scroll akan berubah menampilkan item baru. Namun, jika menggunakannotifyItemRangeInserted(0, newItems.size() - 1)
yangRecyclerView
membuat negara gulir.EDIT: Untuk mengembalikan posisi semu yang persis sama , seperti di, membuatnya terlihat persis seperti itu, kita perlu melakukan sesuatu yang sedikit berbeda (Lihat di bawah cara mengembalikan nilai scrollY yang tepat):
Simpan posisi dan offset seperti ini:
Dan kemudian pulihkan gulungan seperti ini:
Ini mengembalikan daftar ke posisi semu yang sebenarnya . Terlihat jelas karena akan terlihat sama bagi pengguna, tetapi tidak akan memiliki nilai scrollY yang sama (karena kemungkinan perbedaan dalam dimensi tata letak lanskap / potret).
Perhatikan bahwa ini hanya berfungsi dengan LinearLayoutManager.
--- Di bawah ini cara mengembalikan scrollY yang tepat, yang kemungkinan akan membuat daftar terlihat berbeda ---
Terapkan OnScrollListener seperti ini:
Ini akan menyimpan posisi gulir yang tepat setiap saat di mScrollY.
Simpan variabel ini di Bundle Anda, dan pulihkan dalam pemulihan status ke variabel lain , kami akan menyebutnya mStateScrollY.
Setelah pemulihan status dan setelah RecyclerView Anda menyetel ulang semua datanya, setel ulang gulir dengan ini:
Itu dia.
Berhati-hatilah, Anda mengembalikan scroll ke variabel lain, ini penting, karena OnScrollListener akan dipanggil dengan .scrollBy () dan selanjutnya akan menyetel mScrollY ke nilai yang disimpan di mStateScrollY. Jika Anda tidak melakukan ini, mScrollY akan menggandakan nilai scroll (karena OnScrollListener bekerja dengan delta, bukan scroll absolut).
Penghematan negara dalam kegiatan dapat dicapai seperti ini:
Dan untuk memulihkan panggilan ini di onCreate () Anda:
Penyimpanan status dalam fragmen bekerja dengan cara yang sama, tetapi penyimpanan status yang sebenarnya membutuhkan sedikit kerja ekstra, tetapi ada banyak artikel yang membahasnya, jadi Anda seharusnya tidak memiliki masalah untuk mencari tahu caranya, prinsip-prinsip menyimpan gulungan dan memulihkannya tetap sama.
sumber
Ya, Anda dapat menyelesaikan masalah ini dengan membuat konstruktor adaptor hanya satu kali, saya menjelaskan bagian pengkodean di sini:
Sekarang Anda dapat melihat saya telah memeriksa adaptor adalah null atau tidak dan hanya menginisialisasi ketika null.
Jika adaptor tidak null maka saya yakin bahwa saya telah menginisialisasi adaptor saya setidaknya satu kali.
Jadi saya hanya akan menambahkan daftar ke adaptor dan memanggil notifydatasetchanged.
RecyclerView selalu menahan posisi terakhir yang di-scroll, oleh karena itu Anda tidak perlu menyimpan posisi terakhir, cukup panggil notifydatasetchanged, recycler view selalu menyegarkan data tanpa naik ke atas.
Terima kasih Selamat Coding
sumber
Pertahankan posisi scroll dengan menggunakan jawaban @DawnYu untuk membungkus
notifyDataSetChanged()
seperti ini:sumber
Jawaban teratas dari @DawnYu berfungsi, tetapi recyclerview pertama-tama akan menggulir ke atas, lalu kembali ke posisi gulir yang diinginkan sehingga menyebabkan reaksi "berkedip seperti" yang tidak menyenangkan.
Untuk menyegarkan recyclerView, terutama setelah datang dari aktivitas lain, tanpa berkedip, dan mempertahankan posisi gulir, Anda perlu melakukan hal berikut.
Semoga ini membantu.
sumber
Saya belum pernah menggunakan Recyclerview tetapi saya melakukannya di ListView. Kode contoh di Recyclerview:
Ini adalah pendengar saat pengguna menggulir. Overhead kinerja tidak signifikan. Dan posisi pertama yang terlihat akurat seperti ini.
sumber
findFirstVisibleItemPosition
mengembalikan "posisi adaptor dari tampilan pertama yang terlihat", tapi bagaimana dengan offsetnya.Solusinya di sini adalah terus menggulir recyclerview saat pesan baru datang.
Metode onChanged () mendeteksi tindakan yang dilakukan pada recyclerview.
sumber
Itu berhasil untuk saya di Kotlin.
Offset gulir tidak berubah.
sumber
Saya mengalami masalah ini dengan daftar item yang masing-masing memiliki waktu dalam beberapa menit sampai mereka 'jatuh tempo' dan perlu diperbarui. Saya akan memperbarui data dan kemudian, telepon
dan itu akan bergulir ke atas setiap saat. Saya menggantinya dengan
dan itu baik-baik saja. Tidak ada metode lain di utas ini yang berhasil untuk saya. Dalam menggunakan metode ini, itu membuat setiap item berkedip ketika diperbarui jadi saya juga harus meletakkan ini di onCreateView fragmen induk.
sumber
Jika Anda memiliki satu atau beberapa EditText di dalam item recyclerview, nonaktifkan autofokus ini, letakkan konfigurasi ini di tampilan induk recyclerview:
Saya mengalami masalah ini ketika saya memulai aktivitas lain yang diluncurkan dari item recyclerview, ketika saya kembali dan mengatur pembaruan satu bidang dalam satu item dengan notifyItemChanged (posisi) gulungan gerakan RV, dan kesimpulan saya adalah, fokus otomatis EditText Item, kode di atas menyelesaikan masalah saya.
terbaik.
sumber
Kembalikan jika oldPosition dan posisinya sama;
sumber