Wie implementiere ich ein Kontextmenü für RecyclerView?
Anscheinend registerForContextMenu(recyclerView)
funktioniert das Aufrufen nicht. Ich nenne es aus einem Fragment. Hat jemand Erfolg damit gehabt?
android
contextmenu
android-recyclerview
Binoy Babu
quelle
quelle
Antworten:
Sie können nicht direkt diese Methode wie implementieren OnClickListener , OnContextMenuListener usw. weil RecycleView erstreckt android.view.ViewGroup . Wir können diese Methode also nicht direkt anwenden. Wir können diese Methoden in der ViewHolder- Adapterklasse implementieren . Wir können das Kontextmenü in RecycleView folgendermaßen verwenden:
Jetzt gehen wir genauso vor, während wir das Kontextmenü implementieren.
Wenn Sie Schwierigkeiten haben, fragen Sie im Kommentar.
quelle
onContextItemSelected
Aktivität / Fragmentebene.getTitle
funktioniert,getItemId
funktioniert,getMenuInfo
liefert aber null. Also, wie bekommt man das in den GriffViewHolder
?getMenuInfo()
gibt null in zurückonContextItemSelected()
. Vielleicht haben die Leute, die es zum Laufen gebracht haben, eineonCreateContextMenu()
Methode im Blick weiter oben in der Hierarchie (dasRecyclerView
oderFragment
)? Das kann funktionieren, bringt uns dann aber zu anderen Antworten auf diese Frage.menu.add(this.getAdapterPosition(), v.getId(), 0, "Call");
und dann in Ihreritem.getGroupId()
Danke für die Infos und Kommentare. Ich konnte
ContextMenu
für Artikel in erreichenRecyclerview
.Hier ist was ich getan habe
in der
onViewCreated
Methode von Fragment oder deronCreate
Methode von Activity :Dann im Adapter hinzufügen
Lassen Sie die
ViewHolder
Klasse implementierenOnCreateContextMenuListener
onBindViewHolder
Methode AddOnLongClickListener
on the Holder.itemView, um die Position zu erfassen, bevor das Kontextmenü geladen wird:Dann
onViewRecycled
entfernen Sie den Hörer so , dass es keine Referenzfragen. (möglicherweise nicht erforderlich).Schließlich überschreiben Sie im Fragment / Aktivität das
onContextItemSelected
wie unter:quelle
Die aktuelle Antwort ist nicht korrekt. Hier ist eine funktionierende Implementierung:
In Ihrem Fragment (oder Ihrer Aktivität):
Und schließlich in Ihrem ViewHolder:
quelle
getChildPosition()
ist jetzt veraltet. Ich habegetChildAdapterPosition()
stattdessen verwendet.getChildPosition()
ist veraltet incom.android.support:recyclerview-v7:22.0.0
.Versuchen Sie dies für ein
View
Element in recycleViewSie können es verwenden, um Daten für ein
ViewHolder
Element festzulegenquelle
Die Antwort von Prabhakar ist korrekt, aber er hat nicht erklärt, wie man Daten in Bezug auf das gedrückte Element erhält, wenn ein Kontextmenüelement ausgewählt wird. Wir können einen
onContextItemSelected
Rückruf verwenden, sind jedoch in diesem FallContextMenuInfo
nicht verfügbar (null
) (wenn diegetContextMenuInfo()
Methode für eine gedrückte Ansicht nicht überschrieben wird). Die einfachste Lösung besteht also darin,OnMenuItemClickListener
direkt zum hinzuzufügenMenuItem
.quelle
RecyclerView
nur zum ÜberschreibengetContextMenuInfo
usw. dienen sollen, auch wenn dies nicht ganz so effizient ist, wie das Fragment / die Aktivität Klicks verarbeiten zu lassen. Die Zuhörer haben Zugriff auf die Daten im Halter, sodass Sie keine Position benötigen sollten. Und theoretisch könnten Sie die Position beim Binden in Ihrem Adapter trotzdem zwischenspeichern und die Delegierung verwenden, um aus Ihrem Halter herauszurufen, wenn Sie müssen, obwohl die Verwendung derContext
aus einer der gebundenen Ansichten manchmal ausreichend sein kann.@ Renauds Antwort funktionierte für mich, erforderte jedoch zuerst einige Code-Korrekturen. Es ist, als hätte er Ausschnitte aus verschiedenen Iterationen seines Codes gepostet. Die Änderungen, die vorgenommen werden müssen, sind:
RecyclerContextMenuInfo
undRecyclerViewContextMenuInfo
sind die gleiche Klasse. Wähle einen Namen und bleibe dabei.ViewHolder
muss implementiert werdenView.OnLongClickListener
, und denken Sie daran,setOnLongClickListener()
das Element im Konstruktor aufzurufen .onLongClick()
HörergetView().showContextMenu()
ist das völlig falsch. Sie müssenshowContextMenuForChild()
Ihre anrufenContextMenuRecyclerView
, sonst werdenContextMenuInfo
Sie einsteigenonCreateContextMenu()
undonContextItemSelected()
werden null sein.Mein bearbeiteter Code unten:
ContextMenuRecyclerView:
In Ihrem Fragment:
In Ihrem ViewHolder:
Also, stellen Sie sicher , dass Sie ersetzen
RecyclerView
mitContextMenuRecyclerView
im Layout!quelle
recyclerView.showContextMenuForChild(itemView);
durchitemView.showContextMenu()
.Hier ist eine saubere Möglichkeit, den Menükontext für RecyclerView-Elemente zu verwenden
Zunächst benötigen Sie eine Artikelposition
In der Adapterklasse:
In
onBindViewHolder
Hook der benutzerdefinierte Listener:Erstellen Sie in MainActivity (Aktivität / Fragment) ein Feld:
Legen Sie in Ihrem Adapterobjekt den benutzerdefinierten Listener fest:
Zweitens erstellen Sie Ihr Menü
In res -> menu Erstellen Sie eine Datei mit Ihrem Menüpunkt
context_menu_main.xml
:In MainActivity: Implementieren Sie beide
onCreateContextMenu
undonContextItemSelected
:Drittens zurück zu Ihrem Adapterobjekt
Zeigen Sie das Kontextmenü an.
Weitere Infos unter Menüdokumentation
quelle
Hier ist eine einfachere Möglichkeit, dies mit Kotlin zu tun, die für mich funktioniert hat. Die größte Herausforderung besteht darin, die Position des Gegenstandes herauszufinden, der gedrückt wurde. In Ihrem Adapter können Sie dieses Code-Snippet platzieren und es kann die Position des Elements erfassen, für das das Kontextmenü angezeigt wird. das ist alles.
quelle
Ich habe meine Lösung mit der Lösung von @Hardik Shah kombiniert:
In der Aktivität habe ich:
Im Adapter habe ich:
In Fragment habe ich:
quelle
Ich bin vielleicht zu spät zur Party, aber ich habe eine funktionierende Lösung . Ich habe einen Kern dafür gemacht.
Kontextmenü zu RecyclerView hinzufügen
ActivityName.java
RecyclerAdapter.java
quelle
Hallo Leute, es ist eine Alternative herausgekommen, die für mich funktioniert. Ich registriere einfach meine itemView bei registerContextMenu im ViewHolder-Konstruktor und setze auch einen onLongClikcListener auf dieselbe Ansicht. In der Implementierung von onLongClick (View v) erhalte ich einfach die angeklickte Position mit getLayoutPosition () und speichere sie in einer Instanzvariablen (ich habe eine Klasse erstellt, um diese Daten darzustellen, genau wie ContextMenuInfo funktionieren soll), aber wichtiger ist es, dies zu tun Stellen Sie sicher, dass Sie bei dieser Methode false zurückgeben . Jetzt müssen Sie nur noch onContextItemSelected (MenuItem-Element) in sich aufnehmen, die Daten lesen, die Sie in Ihrer Instanzvariablen speichern, und wenn sie gültig sind, fahren Sie mit Ihren Aktionen fort. Hier ist es ein Ausschnitt.
Ich mache ViewHolder implementiert OnLongClickListener, aber Sie können es auf jede Weise tun, die Sie bevorzugen.
Sie können dies auch im Adapter oder in einer anderen Ansicht im ViewHolder (dh einer Textansicht) festlegen. Wichtig ist die Implementierung von onLongClik ().
Das Beste daran ist, dass Sie das LongClick-Ereignis, das in den gewünschten Fällen true zurückgibt, weiterhin verarbeiten können und das conextMenu nicht angezeigt wird.
Diese Methode funktioniert, weil registerForContextView die Ansicht LongClickable macht und wenn es Zeit ist, das ContextMenu zu verarbeiten, ruft das System performLongClick auf, das zuerst eine onLongClick-Implementierung aufruft, und wenn es false zurückgibt, ruft es showContextMenu auf.
quelle
Ich benutze diese Lösung seit einiger Zeit und habe ziemlich gut für mich funktioniert.
Implementieren Sie nun in Ihrem Fragment oder Ihrer Aktivität die folgenden Methoden.
Registrieren Sie sich schließlich für das Kontextmenü in der Recycling-Ansicht
Das sollte funktionieren!
quelle
So können Sie das Kontextmenü für RecyclerView implementieren und die Position des Elements abrufen, für das das Kontextmenüelement ausgewählt wurde:
}}
quelle
Eine Lösung für diejenigen, die beim Anruf die Artikel-ID erhalten möchten
ContextMenu
.Wenn Sie eine
RecyclerView
mit Elementen wie diesen haben (mit anklickbarenImageView
):dann sollten Sie Rückrufe von erhalten
onClickListener
.Adapter
Fragment
Warnung!
Wenn Sie ein
ViewPager
Fragment verwenden, das auf einem Fragment basiert (alle Seiten sind ähnliche Listen), tritt ein Problem auf. Wenn Sie überschreiben, umonContextItemSelected
zu verstehen, welcher Menüpunkt ausgewählt wurde, erhalten Sie auf der ersten Seite eine Listenelement-ID! Um dieses Problem zu beheben, lesen Sie Falsches Fragment in ViewPager empfängt den Aufruf onContextItemSelected .quelle
Ich habe Probleme damit, weil Android dies in RecyclerView, das für ListView sehr gut funktioniert hat, für mich nicht gut handhabt.
Das schwierigste Teil ist, dass das ContextMenuInfo-Teil in eine Ansicht eingebettet ist, die Sie nur durch Überschreiben der Ansicht anhängen können.
Sie benötigen also einen Wrapper, mit dem Sie die Positionsinformationen an die Aktivität senden können.
}}
Wenn Sie dann in Ihrem RecyclerAdapter ViewHolders erstellen, müssen Sie den Wrapper als Stammansicht festlegen und in jeder Ansicht das Kontextmenü registrieren.
}}
Und schließlich können Sie in Ihrer Aktivität das tun, was Sie normalerweise tun:
quelle
Am besten verwenden Sie das Kontextmenü mit der Recycler-Ansicht, wenn Sie eine benutzerdefinierte Recycler-Ansicht erstellen, die
getContextMenuInfo()
Methode überschreiben und Ihre eigene Instanz des Kontextmenü-Infoobjekts zurückgeben, damit Sie Positionen abrufen können, wenn es erstellt wurde und wenn auf das Menü geklickt wird:Schauen Sie sich diesen Kern an, den ich erstellt habe:
https://gist.github.com/resengupta/2b2e26c949b28f8973e5
quelle
Wenn Sie vermeiden möchten, das Menü in Ihrem Code im Adapter / ViewHolder manuell zu definieren, können Sie ein Popup-Menü verwenden und die Menüoptionen aus einer Standardressourcendatei menu.xml aufblasen.
Das folgende Beispiel zeigt dies, einschließlich der Möglichkeit, einen Listener zu übergeben, den Sie in Ihrem Fragment / Ihrer Aktivität implementieren können, um auf Kontextmenüklicks zu reagieren.
Vollständiger Überblick hier https://gist.github.com/brettwold/45039b7f02ce752ae0d32522a8e2ad9c
quelle
Sie können OnCreateContextMenuListener beim Binden an ViewHolder übergeben. Dieser Listener kann für jedes Datenelement ein benutzerdefiniertes Menü erstellen. Fügen Sie einfach setOnCreateContextMenuListener in Ihren ViewHolder ein und rufen Sie es während der Bindung auf.
}}
Im Adapter:
quelle
In meinem Fall musste ich Daten aus meinem Fragment in der
onContextItemSelected()
Methode verwenden. Die Lösung bestand darin, eine Instanz des Fragments an meinen Adapter zu übergeben und das Ansichtselement im Ansichtshalter zu registrieren:Dann
onCreateContextMenu()
können Sie den Index in einer lokalen Variablen speichern:selectedViewIndex = (int)v.getTag();
und abrufen in
onContextItemSelected()
quelle
Als ich zum ersten Mal mit normalen Adaptern auf dieses Problem stieß, erstellte ich meine eigene benutzerdefinierte Ansichtsunterklasse und speicherte das benötigte Material darin. Ich mochte diese Lösung wirklich nicht und verbrachte viel Zeit damit, mir die großartigen Ideen anzusehen, die die Leute vorgeschlagen haben, und entschied, dass ich sie nicht besser mochte. Also habe ich alles zusammengefügt, eine Weile herumgeschüttelt und etwas Neues herausgebracht, das mir gefällt.
Wir beginnen mit ein paar Utility-Klassen. ContextMenuHandler ist eine Schnittstelle für jedes Objekt, das das Kontextmenü verarbeiten soll. In der Praxis wird dies eine ViewHolder-Unterklasse sein, aber theoretisch könnte es fast alles sein
Als nächstes folgt eine Schnittstelle, die von jeder Ansicht implementiert werden muss, die als unmittelbares untergeordnetes Element einer RecyclerView verwendet werden soll.
Als Nächstes muss jede Ansicht, die als untergeordnetes Element einer RecylcerView ein Kontextmenü erstellen soll, ViewWIthContextMenu implementieren. In meinem Fall brauchte ich nur eine Unterklasse von LinearLayout.
Und schließlich benötigen wir eine aufgemotzte Fragment-Klasse, um die Kontextmenü-Aufrufe abzufangen und an den entsprechenden Handler umzuleiten.
Mit all dem ist die endgültige Implementierung ziemlich einfach. Das Hauptfragment muss FragmentWithContextMenu unterordnen. Es richtet das Haupt-RecylerWindow normal ein und übergibt sich selbst an die Adapter-Unterklasse. Die Adapter-Unterklasse sieht aus wie
Das ist alles. Es scheint alles zu funktionieren. Alle Utility-Klassen wurden in ein separates Kontextmenü-Paket gestellt, sodass ich die Klassennamen hätte angeben können, die mit den dortigen Klassen übereinstimmen, aber ich dachte, das wäre verwirrender.
quelle
Ok, basierend auf der Antwort von @ Flexo werde ich mPosition bestellen ...
dann verwende ich in onContextItemSelected
Und alles funktioniert gut Ich bekomme leicht die Position des Arrays
quelle