Bagaimana cara menerapkan menu konteks untuk RecyclerView?
Rupanya panggilan registerForContextMenu(recyclerView)
tidak berfungsi. Saya menyebutnya dari sebuah fragmen. Apakah ada yang berhasil menerapkan ini?
android
contextmenu
android-recyclerview
Binoy Babu
sumber
sumber
Jawaban:
Anda tidak dapat langsung mengimplementasikan metode ini seperti onClickListener , OnContextMenuListener , dll. Karena RecycleView memperluas android.view.ViewGroup . Jadi kami tidak bisa langsung menggunakan metode ini. Kita bisa mengimplementasikan metode ini di kelas adaptor ViewHolder . Kita bisa menggunakan menu konteks di RecycleView seperti ini:
Sekarang kita mengikuti prosedur yang sama saat mengimplementasikan menu konteks.
Jika Anda mengalami kesulitan, tanyakan dalam komentar.
sumber
onContextItemSelected
di level aktivitas / fragmen.getTitle
berfungsi,getItemId
berfungsi, tetapigetMenuInfo
memberikan null. Jadi, bagaimana cara mendapatkannyaViewHolder
?getMenuInfo()
mengembalikan nolonContextItemSelected()
. Mungkin orang-orang yang berhasil membuatnya bekerja kebetulan memilikionCreateContextMenu()
metode untuk melihat lebih jauh hierarki (RecyclerView
atauFragment
)? Itu bisa berhasil tetapi kemudian membawa kita ke jawaban lain untuk pertanyaan ini.menu.add(this.getAdapterPosition(), v.getId(), 0, "Call");
dan kemudian dalam pengujian metode panggilan balik untukitem.getGroupId()
mendapatkan posisiTerima kasih atas info dan komentarnya. Saya bisa meraih
ContextMenu
item dalamRecyclerview
.Inilah yang saya lakukan
dalam
onViewCreated
metode Fragmen atau metode AktivitasonCreate
:Kemudian di Adaptor tambahkan
membuat
ViewHolder
kelas mengimplementasikanOnCreateContextMenuListener
onBindViewHolder
metode tambahkanOnLongClickListener
pada holder.itemView untuk menangkap posisi sebelum menu konteks dimuat:Kemudian di
onViewRecycled
hapus Listener agar tidak ada masalah referensi. (mungkin tidak diperlukan).Akhirnya di Fragment / Activity menimpa
onContextItemSelected
seperti di bawah:sumber
Jawaban saat ini tidak benar. Berikut implementasi yang berfungsi:
Di Fragmen (atau Aktivitas) Anda:
Dan terakhir, di ViewHolder Anda:
sumber
getChildPosition()
sekarang sudah usang. Saya menggunakangetChildAdapterPosition()
sebagai gantinya.getChildPosition()
sudah tidak berlaku lagi dicom.android.support:recyclerview-v7:22.0.0
.Coba ini untuk
View
item di recycleViewAnda dapat menggunakannya dengan mengatur data ke
ViewHolder
itemsumber
Jawaban Prabhakar benar, tapi dia tidak menjelaskan bagaimana cara mendapatkan suatu data, terkait item yang ditekan, ketika item menu konteks dipilih. Kita bisa menggunakan
onContextItemSelected
callback, tetapiContextMenuInfo
tidak tersedia (null
) dalam kasus ini (jikagetContextMenuInfo()
metode tidak diganti untuk tampilan yang ditekan). Jadi, solusi paling sederhana adalah menambahkanOnMenuItemClickListener
langsung keMenuItem
.sumber
RecyclerView
hanya untuk ditimpagetContextMenuInfo
, dll., Meskipun tidak seefisien membiarkan fragmen / aktivitas menangani klik. Pendengar akan memiliki akses ke data di pemegang, jadi Anda tidak perlu posisi. Dan secara teoritis Anda dapat menyimpan posisi setelah mengikat di adaptor Anda, dan menggunakan delegasi untuk memanggil pemegang Anda jika Anda harus, meskipun menggunakanContext
dari salah satu tampilan terikat terkadang sudah cukup.@ Jawaban Renaud berhasil untuk saya tetapi memerlukan beberapa perbaikan kode terlebih dahulu. Sepertinya dia memposting potongan dari beberapa iterasi berbeda dari kodenya. Perubahan yang perlu dilakukan adalah:
RecyclerContextMenuInfo
danRecyclerViewContextMenuInfo
merupakan kelas yang sama. Pilih nama dan pertahankan.ViewHolder
harus menerapkanView.OnLongClickListener
, dan ingat untuk memanggilsetOnLongClickListener()
pada item dalam konstruktor.onLongClick()
pendengar,getView().showContextMenu()
benar-benar salah. Anda harus memanggilshowContextMenuForChild()
AndaContextMenuRecyclerView
, jika tidak,ContextMenuInfo
Anda masukonCreateContextMenu()
danonContextItemSelected()
akan menjadi nol.Kode yang saya edit di bawah ini:
ContextMenuRecyclerView:
Dalam fragmen Anda:
Di ViewHolder Anda:
Juga, pastikan Anda mengganti
RecyclerView
denganContextMenuRecyclerView
dalam tata letak Anda!sumber
recyclerView.showContextMenuForChild(itemView);
denganitemView.showContextMenu()
.Berikut adalah cara bersih untuk menggunakan konteks menu pada item RecyclerView
Pertama, Anda membutuhkan posisi barang
Di kelas Adaptor:
Dalam
onBindViewHolder
kaitannya dengan pendengar khusus:Dalam MainActivity (Activity / Fragment) buat bidang:
Di objek Adapter Anda, setel pendengar kustom:
Kedua, buat menu Anda
Di res -> menu Buat file dengan item menu Anda
context_menu_main.xml
:Dalam MainActivity: Terapkan keduanya
onCreateContextMenu
danonContextItemSelected
:Ketiga, kembali ke objek Adaptor Anda
tampilkan menu konteks.
Info lebih lanjut di Dokumentasi Menu
sumber
Berikut cara yang lebih sederhana untuk melakukannya dengan Kotlin yang berhasil untuk saya. Tantangan utamanya adalah mencari tahu posisi item yang ditekan. Di dalam adaptor Anda, Anda dapat menempatkan cuplikan kode ini dan itu akan dapat menangkap posisi item yang menu konteksnya ditampilkan; itu saja.
sumber
Saya mungkin terlambat ke pesta tetapi saya memiliki solusi yang berfungsi . Saya telah membuat intisari untuk itu.
Tambahkan Menu Konteks ke RecyclerView
ActivityName.java
RecyclerAdapter.java
sumber
Saya telah menggabungkan solusi saya dengan solusi dari @Hardik Shah:
Dalam aktivitas saya memiliki:
Di Adaptor saya punya:
Dalam fragmen saya memiliki:
sumber
Halo teman-teman, keluar dengan satu alternatif yang cocok untuk saya. Saya baru saja mendaftarkan itemView saya dengan registerContextMenu dan Konstruktor ViewHolder, juga menyetel onLongClikcListener ke View yang sama. Dalam implementasi onLongClick (View v), saya cukup mendapatkan posisi diklik dengan getLayoutPosition () dan menyimpan dalam variabel instan (saya membuat kelas untuk mewakili data ini, seperti ContextMenuInfo diharapkan berfungsi), tetapi yang lebih penting adalah membuat yakin Anda mengembalikan false dalam metode ini. Yang harus Anda lakukan sekarang adalah di onContextItemSelected (item MenuItem), baca data yang Anda simpan di variabel instance Anda dan jika valid, lanjutkan dengan tindakan Anda. Ini cuplikannya.
Saya membuat ViewHolder mengimplementasikan OnLongClickListener, tetapi Anda dapat melakukannya dengan cara apa pun yang Anda inginkan.
Anda juga dapat menyetel ini di adaptor, atau ke Tampilan lain yang Anda miliki di ViewHolder (yaitu TextView). Yang penting adalah implementasi onLongClik ().
Bagian terbaiknya adalah Anda masih bisa memproses kejadian LongClick yang mengembalikan true dalam kasus yang Anda inginkan, dan conextMenu tidak akan muncul.
Metode ini berfungsi karena registerForContextView membuat View LongClickable, dan saat waktunya memproses ContextMenu, sistem akan memanggil performLongClick, yang pertama-tama memanggil implementasi onLongClick, dan jika menampilkan false, maka sistem akan memanggil showContextMenu.
sumber
Saya telah menggunakan solusi ini untuk beberapa waktu sekarang dan telah bekerja cukup baik untuk saya.
Sekarang di fragmen atau Aktivitas Anda, terapkan metode berikut.
Akhirnya Daftarkan ke contextMenu di recyclerview
Seharusnya itu berhasil!
sumber
Berikut adalah cara mengimplementasikan menu konteks untuk RecyclerView, dan mendapatkan posisi item, yang item menu konteksnya telah dipilih:
}
sumber
Solusi bagi yang ingin mendapatkan id item saat menelepon
ContextMenu
.Jika Anda memiliki
RecyclerView
dengan item seperti ini (mengandung dapat diklikImageView
):maka Anda akan menerima panggilan balik dari
onClickListener
.Adaptor
Pecahan
Peringatan!
Jika Anda menggunakan
ViewPager
berdasarkan satu fragmen (semua halaman adalah daftar serupa), Anda akan menghadapi masalah. Saat Anda menimpaonContextItemSelected
untuk memahami item menu apa yang dipilih, Anda akan mendapatkan id item daftar dari halaman pertama! Untuk mengatasi masalah ini, lihat Fragmen yang salah di ViewPager menerima panggilan onContextItemSelected .sumber
Saya telah berjuang dalam hal ini karena Android tidak menangani ini dengan baik untuk saya di RecyclerView, yang bekerja sangat baik untuk ListView.
Bagian yang paling sulit adalah bagian ContextMenuInfo disematkan di dalam Tampilan, yang tidak dapat Anda lampirkan dengan mudah selain menimpa Tampilan.
Jadi, Anda memerlukan pembungkus yang membantu Anda mengirimkan info posisi ke Aktivitas.
}
Kemudian di RecyclerAdapter, saat Anda membuat ViewHolders, Anda perlu menyetel Wrapper sebagai tampilan root, dan mendaftarkan contextMenu pada setiap tampilan.
}
Dan terakhir, dalam Aktivitas Anda, Anda akan dapat melakukan apa yang biasanya Anda lakukan:
sumber
Yang terbaik adalah menggunakan menu Konteks dengan tampilan pendaur ulang adalah jika Anda membuat tampilan pendaur ulang khusus dan menimpa
getContextMenuInfo()
metode dan mengembalikan instance Anda sendiri dari objek info menu Konteks sehingga Anda dapat mengambil posisi saat dibuat dan saat menu diklik:Lihatlah inti yang telah saya buat ini:
https://gist.github.com/resengupta/2b2e26c949b28f8973e5
sumber
Memperluas beberapa jawaban di atas sedikit, jika Anda ingin menghindari mendefinisikan menu secara manual dalam kode Anda di Adapter / ViewHolder, maka Anda dapat menggunakan PopupMenu dan memekarkan opsi menu dari file sumber menu.xml standar.
Contoh di bawah menunjukkan ini termasuk kemampuan untuk meneruskan pemroses yang bisa Anda terapkan di Fragmen / Aktivitas untuk merespons klik menu konteks.
Inti lengkapnya di sini https://gist.github.com/brettwold/45039b7f02ce752ae0d32522a8e2ad9c
sumber
Anda bisa meneruskan OnCreateContextMenuListener ke ViewHolder saat bind. Listener ini dapat membuat menu kustom untuk setiap item data. Cukup tambahkan setOnCreateContextMenuListener di ViewHolder Anda dan panggil selama pengikatan.
}
Di adaptor:
sumber
Dalam kasus saya, saya harus menggunakan data dari fragmen saya dalam
onContextItemSelected()
metode ini. Solusi yang akhirnya saya lakukan adalah meneruskan instance fragmen ke adaptor saya dan mendaftarkan item tampilan di view holder:Kemudian
onCreateContextMenu()
Anda dapat menyimpan indeks ke variabel lokal:selectedViewIndex = (int)v.getTag();
dan mengambilnya kembali
onContextItemSelected()
sumber
Pertama kali saya mengalami masalah ini dengan adaptor normal, saya akhirnya membuat subkelas View kustom saya sendiri dan menyimpan hal-hal yang saya butuhkan di dalamnya. Saya benar-benar tidak menyukai solusi itu dan menghabiskan banyak waktu untuk melihat ide-ide hebat yang telah diusulkan orang, dan memutuskan bahwa saya tidak menyukainya lebih baik. Jadi saya mengumpulkan semuanya, mengguncangnya sebentar, dan keluar dengan sesuatu yang baru yang saya suka.
Kami mulai dengan beberapa kelas utilitas. ContextMenuHandler adalah antarmuka untuk objek apa pun yang akan menangani menu konteks. Dalam praktiknya, ini akan menjadi subkelas ViewHolder, tetapi secara teori bisa jadi apa saja
Berikutnya adalah Antarmuka yang harus diimplementasikan oleh Tampilan apa pun yang akan digunakan sebagai turunan langsung dari RecyclerView.
Selanjutnya, setiap tampilan yang akan membuat menu konteks sebagai anak dari RecylcerView harus mengimplementasikan ViewWIthContextMenu. Dalam kasus saya, saya hanya membutuhkan subclass LinearLayout.
Dan terakhir, kita membutuhkan kelas Fragment yang telah ditingkatkan untuk mencegat panggilan menu konteks dan mengarahkannya ke penangan yang sesuai.
Dengan semua ini di tempat, implementasi akhir cukup sederhana. Fragmen utama harus subkelas FragmentWithContextMenu. Ini mengatur RecylerWindow utama secara normal dan meneruskan dirinya sendiri ke subkelas Adapter. Subkelas Adaptor terlihat seperti
Itu saja. Semuanya tampaknya berhasil. Itu meletakkan semua kelas utilitas dalam paket menu konteks terpisah sehingga saya bisa memberikan nama kelas yang cocok dengan kelas yang ada subclass, tapi saya pikir akan lebih membingungkan.
sumber
Ok, berdasarkan jawaban @ Flexo, mPosition akan saya pesan ...
lalu di onContextItemSelected saya gunakan
Dan semua bekerja dengan baik saya mendapatkan posisi array dengan mudah
sumber