Comment implémenter le menu contextuel pour RecyclerView?
Apparemment appeler registerForContextMenu(recyclerView)
ne fonctionne pas. Je l'appelle à partir d'un fragment. Quelqu'un a-t-il réussi à mettre en œuvre cela?
android
contextmenu
android-recyclerview
Binoy Babu
la source
la source
Réponses:
Vous ne pouvez pas implémenter directement ces méthodes comme onClickListener , OnContextMenuListener etc. car RecycleView étend android.view.ViewGroup . Nous ne pouvons donc pas utiliser directement ces méthodes. Nous pouvons implémenter ces méthodes dans la classe d'adaptateur ViewHolder . Nous pouvons utiliser le menu contextuel dans RecycleView comme ceci:
Maintenant, nous suivons la même procédure tout en implémentant le menu contextuel.
Si vous rencontrez des difficultés, demandez en commentaire.
la source
onContextItemSelected
d'activité / fragment.getTitle
fonctionne,getItemId
fonctionne, maisgetMenuInfo
délivre null. Alors, comment obtenir leViewHolder
?getMenuInfo()
renvoie null dansonContextItemSelected()
. Peut-être que les gens qui l'ont fait fonctionner ont eu uneonCreateContextMenu()
méthode dans une vue plus haut dans la hiérarchie (leRecyclerView
ouFragment
)? Cela peut fonctionner mais nous amène ensuite à d'autres réponses à cette question.menu.add(this.getAdapterPosition(), v.getId(), 0, "Call");
puis dans votre test de méthode de rappel pouritem.getGroupId()
obtenir la positionMerci pour les informations et les commentaires. J'ai pu réaliser
ContextMenu
des objets enRecyclerview
.Voici ce que j'ai fait
dans la
onViewCreated
méthode Fragment ou la méthode ActivityonCreate
:Puis dans l'adaptateur, ajoutez
faire
ViewHolder
implémenter la classeOnCreateContextMenuListener
onBindViewHolder
addOnLongClickListener
on the holder.itemView pour capturer la position avant le chargement du menu contextuel:Ensuite,
onViewRecycled
supprimez l'écouteur afin qu'il n'y ait aucun problème de référence. (peut ne pas être requis).Enfin, dans le fragment / activité, remplacez
onContextItemSelected
comme ci-dessous:la source
La réponse actuelle n'est pas correcte. Voici une implémentation fonctionnelle:
Dans votre fragment (ou activité):
Et enfin, dans votre ViewHolder:
la source
getChildPosition()
est obsolète maintenant. J'ai utilisé à lagetChildAdapterPosition()
place.getChildPosition()
est obsolète danscom.android.support:recyclerview-v7:22.0.0
.Essayez ceci pour un
View
élément dans recycleViewVous pouvez l'utiliser pour définir des données sur un
ViewHolder
élémentla source
La réponse de Prabhakar est correcte, mais il n'a pas expliqué comment obtenir une donnée, liée à l'élément pressé, lorsqu'un élément du menu contextuel est sélectionné. Nous pouvons utiliser le
onContextItemSelected
rappel, maisContextMenuInfo
n'est pas disponible (null
) dans ce cas (si lagetContextMenuInfo()
méthode n'est pas remplacée pour une vue pressée). Ainsi, la solution la plus simple consiste à ajouterOnMenuItemClickListener
directement au fichierMenuItem
.la source
RecyclerView
juste pour remplacer,getContextMenuInfo
etc., même si ce n'est pas aussi efficace que de laisser le fragment / l'activité gérer les clics. Les auditeurs auront accès aux données dans le support, vous ne devriez donc pas avoir besoin de position. Et théoriquement, vous pouvez de toute façon mettre en cache la position lors de la liaison dans votre adaptateur et utiliser la délégation pour appeler votre titulaire si vous le devez, bien que l'utilisation de l'Context
une des vues liées puisse parfois suffire.La réponse de @ Renaud a fonctionné pour moi mais a d'abord nécessité plusieurs corrections de code. C'est comme s'il avait publié des extraits de plusieurs itérations différentes de son code. Les modifications à apporter sont:
RecyclerContextMenuInfo
etRecyclerViewContextMenuInfo
sont de la même classe. Choisissez un nom et respectez-le.ViewHolder
doit implémenterView.OnLongClickListener
et n'oubliez pas d'appelersetOnLongClickListener()
l'élément dans le constructeur.onLongClick()
auditeur,getView().showContextMenu()
est complètement faux. Vous devez appelershowContextMenuForChild()
votreContextMenuRecyclerView
, sinonContextMenuInfo
vous entrezonCreateContextMenu()
etonContextItemSelected()
sera nul.Mon code modifié ci-dessous:
ContextMenuRecyclerView:
Dans votre fragment:
Dans votre ViewHolder:
Assurez-vous également de remplacer
RecyclerView
parContextMenuRecyclerView
dans votre mise en page!la source
recyclerView.showContextMenuForChild(itemView);
paritemView.showContextMenu()
.Voici une manière propre d'utiliser le contexte de menu sur les éléments RecyclerView
Tout d'abord, vous avez besoin d'une position d'article
Dans la classe Adapter:
En
onBindViewHolder
crochet l'auditeur personnalisé:Dans MainActivity (Activity / Fragment), créez un champ:
Dans votre objet Adapter, définissez l'écouteur personnalisé:
Deuxièmement, créez votre menu
Dans res -> menu Créer un fichier contenant votre élément de menu
context_menu_main.xml
:Dans MainActivity: implémentez à la fois
onCreateContextMenu
etonContextItemSelected
:Troisièmement, revenons à votre objet Adapter
afficher le menu contextuel.
Plus d'informations sur la documentation des menus
la source
Voici un moyen plus simple de le faire avec Kotlin qui a fonctionné pour moi. Le défi majeur est de déterminer la position de l'élément qui a été pressé. À l'intérieur de votre adaptateur, vous pouvez placer cet extrait de code et il pourra capturer la position de l'élément pour lequel le menu contextuel est affiché; c'est tout.
la source
J'ai combiné ma solution avec la solution de @Hardik Shah:
Dans l'activité j'ai:
Dans l'adaptateur, j'ai:
En fragment, j'ai:
la source
Je suis peut-être en retard à la fête mais j'ai une solution de travail . J'en ai fait l'essentiel.
Ajouter un menu contextuel à RecyclerView
ActivityName.java
RecyclerAdapter.java
la source
Bonjour les gars, a sorti une alternative qui fonctionne pour moi. Je viens d'enregistrer mon itemView avec registerContextMenu et le constructeur ViewHolder, définissez également un onLongClikcListener sur la même vue. Dans l'implémentation onLongClick (View v), j'obtiens simplement la position cliquée avec getLayoutPosition () et l'enregistre dans une variable d'instance (j'ai créé une classe pour représenter ces données, tout comme ContextMenuInfo devrait fonctionner), mais le plus important est de faire assurez-vous de retourner false dans cette méthode. Tout ce que vous avez à faire maintenant est en vous sur onContextItemSelected (élément MenuItem), lisez les données que vous stockez dans votre variable d'instance et si elles sont valides, poursuivez vos actions. Ici, c'est un extrait.
Je fais que ViewHolder implémente OnLongClickListener, mais vous pouvez le faire de la manière que vous préférez.
Vous pouvez également le définir dans l'adaptateur ou dans une autre vue que vous avez dans le ViewHolder (c'est-à-dire un TextView). L'important est l'implémentation onLongClik ().
La meilleure partie est que vous pouvez toujours traiter l'événement LongClick en retournant true dans les cas que vous souhaitez, et le conextMenu n'apparaîtra pas.
Cette méthode fonctionne car registerForContextView rend la vue LongClickable, et lorsqu'il est temps de traiter le ContextMenu, le système appelle performLongClick, qui appelle d'abord une implémentation onLongClick, et si elle retourne false, il appelle ensuite showContextMenu.
la source
J'utilise cette solution depuis un certain temps maintenant et cela a très bien fonctionné pour moi.
Maintenant, dans votre fragment ou activité, implémentez les méthodes suivantes.
Enfin, inscrivez-vous au contexteMenu sur la vue de recyclage
Cela devrait fonctionner!
la source
Voici comment vous pouvez implémenter le menu contextuel pour RecyclerView et obtenir la position de l'élément, pour lequel l'élément de menu contextuel a été sélectionné:
}
la source
Une solution pour ceux qui veulent obtenir l'identifiant de l'article lors de l'appel
ContextMenu
.Si vous avez un
RecyclerView
avec des éléments comme celui-ci (contenant cliquableImageView
):alors vous devriez recevoir des rappels de
onClickListener
.Adaptateur
Fragment
Avertissement!
Si vous utilisez un
ViewPager
basé sur un fragment (toutes les pages sont des listes similaires), vous rencontrerez un problème. Lorsque vous remplacezonContextItemSelected
pour comprendre quel élément de menu a été sélectionné, vous obtiendrez un identifiant d'élément de liste à partir de la première page! Pour surmonter ce problème, voir Un fragment incorrect dans ViewPager reçoit un appel onContextItemSelected .la source
J'ai eu du mal à cela car Android ne gère pas cela bien pour moi dans RecyclerView, qui fonctionnait très bien pour ListView.
L'élément le plus difficile est que l'élément ContextMenuInfo est incorporé dans une vue, que vous ne pouvez pas facilement attacher autrement qu'en remplaçant la vue.
Vous aurez donc besoin d'un wrapper qui vous aidera à fournir les informations de position à l'activité.
}
Ensuite, dans votre RecyclerAdapter, lorsque vous créez ViewHolders, vous devez définir le Wrapper comme vue racine et enregistrer contextMenu sur chaque vue.
}
Et enfin, dans votre activité, vous serez en mesure de faire ce que vous faites habituellement:
la source
Le mieux était d'utiliser le menu contextuel avec la vue recycleur si vous créez une vue recycleur personnalisée et remplacez la
getContextMenuInfo()
méthode et renvoyez votre propre instance de l'objet d'informations du menu contextuel afin que vous puissiez récupérer des positions lors de sa création et lorsque vous cliquez sur le menu:Jetez un œil à l'essentiel que j'ai créé:
https://gist.github.com/resengupta/2b2e26c949b28f8973e5
la source
En développant un peu certaines des réponses ci-dessus, si vous souhaitez éviter de définir manuellement le menu dans votre code dans Adapter / ViewHolder, vous pouvez utiliser un PopupMenu et gonfler les options de menu à partir d'un fichier de ressources menu.xml standard.
L'exemple ci-dessous montre cela, y compris la possibilité de transmettre un écouteur que vous pouvez implémenter dans votre fragment / activité pour répondre aux clics du menu contextuel.
L'essentiel ici https://gist.github.com/brettwold/45039b7f02ce752ae0d32522a8e2ad9c
la source
Vous pouvez passer OnCreateContextMenuListener dans ViewHolder lors de la liaison. Cet écouteur peut créer un menu personnalisé pour chaque élément de données. Ajoutez simplement setOnCreateContextMenuListener dans votre ViewHolder et appelez-le pendant la liaison.
}
Dans l'adaptateur:
la source
Dans mon cas, j'ai dû utiliser les données de mon fragment dans la
onContextItemSelected()
méthode. La solution avec laquelle j'ai fini par utiliser était de passer une instance du fragment dans mon adaptateur et d'enregistrer l'élément de vue dans le support de vue:Ensuite,
onCreateContextMenu()
vous pouvez enregistrer l'index dans une variable locale:selectedViewIndex = (int)v.getTag();
et récupérez-le dans
onContextItemSelected()
la source
La première fois que j'ai rencontré ce problème avec des adaptateurs normaux, j'ai fini par créer ma propre sous-classe View personnalisée et y stocker les éléments dont j'avais besoin. Je n'aimais vraiment pas cette solution et j'ai passé beaucoup de temps à regarder les bonnes idées que les gens avaient proposées, et j'ai décidé que je ne les aimais pas mieux. Alors j'ai en quelque sorte tout mis ensemble, je l'ai secoué pendant un moment et je suis sorti avec quelque chose de nouveau que j'aime.
Nous commençons avec quelques classes d'utilité. ContextMenuHandler est une interface pour n'importe quel objet qui va gérer le menu contextuel. En pratique, cela va être une sous-classe ViewHolder, mais en théorie, cela pourrait être à peu près n'importe quoi
Vient ensuite une interface qui doit être implémentée par toute vue qui sera utilisée comme enfant immédiat d'un RecyclerView.
Ensuite, toute vue qui va créer un menu contextuel en tant qu'enfant d'un RecylcerView doit implémenter ViewWIthContextMenu. Dans mon cas, je n'avais besoin que d'une sous-classe de LinearLayout.
Et enfin, nous avons besoin d'une classe Fragment renforcée pour intercepter les appels du menu contextuel et les rediriger vers le gestionnaire approprié.
Avec tout cela en place, la mise en œuvre finale est assez simple. Le fragment principal doit sous-classer FragmentWithContextMenu. Il configure normalement la RecylerWindow principale et passe à la sous-classe Adapter. La sous-classe Adapter ressemble à
C'est à peu près ça. Tout semble fonctionner. Il a mis toutes les classes d'utilitaires dans un package contextmenu séparé afin que j'aie pu donner les noms de classes qui correspondent aux classes qu'il y a sous-classer, mais j'ai pensé que ce serait plus déroutant.
la source
Ok, d'après la réponse de @ Flexo, je vais mettre mPosition à l'ordre ...
puis dans onContextItemSelected j'utilise
Et tout fonctionne bien, j'obtiens facilement la position du tableau
la source