¿Cómo implemento el menú contextual para RecyclerView?
aparentemente llamar registerForContextMenu(recyclerView)
no funciona? Lo llamo desde un fragmento. ¿Alguien tuvo éxito al implementar esto?
android
contextmenu
android-recyclerview
Binoy Babu
fuente
fuente
Respuestas:
No puede implementar directamente estos métodos como onClickListener , OnContextMenuListener , etc. porque RecycleView extiende android.view.ViewGroup . Entonces no podemos usar directamente este método. Podemos implementar estos métodos en la clase de adaptador ViewHolder . Podemos usar el menú contextual en RecycleView de esta manera:
Ahora seguimos el mismo procedimiento mientras implementamos el menú contextual.
Si tiene alguna dificultad, pregunte en un comentario.
fuente
onContextItemSelected
de actividad / fragmento.getTitle
funciona,getItemId
funciona, perogetMenuInfo
entrega nula. Entonces, ¿cómo conseguirloViewHolder
?getMenuInfo()
devuelve nulo enonContextItemSelected()
. ¿Quizás las personas que lo hicieron funcionar tienen unonCreateContextMenu()
método en una vista más arriba en la jerarquía (elRecyclerView
oFragment
)? Eso puede funcionar, pero luego nos lleva a otras respuestas a esta pregunta.menu.add(this.getAdapterPosition(), v.getId(), 0, "Call");
y luego en su método de devolución de llamada paraitem.getGroupId()
obtener la posiciónGracias por la información y los comentarios. Pude lograr
ContextMenu
artículos enRecyclerview
.Aquí esta lo que hice
en el
onViewCreated
método de Fragment o elonCreate
método de Activity :Luego, en Adaptador, agregue
hacer que la
ViewHolder
clase implementeOnCreateContextMenuListener
onBindViewHolder
agregueOnLongClickListener
el método holder.itemView para capturar la posición antes de que se cargue el menú contextual:Luego,
onViewRecycled
elimine el Listener para que no haya problemas de referencia. (puede que no sea necesario).Finalmente, en el Fragmento / Actividad anule lo
onContextItemSelected
siguiente:fuente
La respuesta actual no es correcta. Aquí hay una implementación funcional:
En su Fragmento (o Actividad):
Y finalmente, en su ViewHolder:
fuente
getChildPosition()
ahora está en desuso. Usé en sugetChildAdapterPosition()
lugar.getChildPosition()
está obsoleto encom.android.support:recyclerview-v7:22.0.0
.Pruebe esto para un
View
artículo en recyclingViewPuede usarlo para configurar datos en un
ViewHolder
elementofuente
La respuesta de Prabhakar es correcta, pero no explicó cómo obtener datos, relacionados con el elemento presionado, cuando se selecciona un elemento del menú contextual. Podemos usar la
onContextItemSelected
devolución de llamada, peroContextMenuInfo
no está disponible (null
) en este caso (si elgetContextMenuInfo()
método no se anula para una vista presionada). Entonces, la solución más simple es agregarOnMenuItemClickListener
directamente alMenuItem
.fuente
RecyclerView
solo para anulargetContextMenuInfo
, etc., incluso si no es tan eficiente como dejar que el fragmento / actividad maneje los clics. Los oyentes tendrán acceso a los datos en el soporte, por lo que no debería necesitar posición. Y, en teoría, podría almacenar en caché la posición al vincularse en su adaptador de todos modos, y usar la delegación para llamar a su titular si es necesario, aunque usarContext
desde una de las vistas vinculadas a veces puede ser suficiente.La respuesta de @ Renaud funcionó para mí, pero primero requirió varias correcciones de código. Es como si hubiera publicado fragmentos de varias iteraciones diferentes de su código. Los cambios que deben realizarse son:
RecyclerContextMenuInfo
yRecyclerViewContextMenuInfo
son de la misma clase. Elija un nombre y apéguese a él.ViewHolder
debe poner en prácticaView.OnLongClickListener
, y recordar a llamarsetOnLongClickListener()
en el elemento en el constructor.onLongClick()
oyente,getView().showContextMenu()
está completamente equivocado. Debes llamarshowContextMenuForChild()
a tuContextMenuRecyclerView
, de lo contrario elContextMenuInfo
entrarásonCreateContextMenu()
yonContextItemSelected()
será nulo.Mi código editado a continuación:
ContextMenuRecyclerView:
En tu fragmento:
En su ViewHolder:
Además, ¡asegúrese de reemplazar
RecyclerView
conContextMenuRecyclerView
en su diseño!fuente
recyclerView.showContextMenuForChild(itemView);
poritemView.showContextMenu()
.Aquí hay una forma limpia de usar el contexto del menú en los elementos de RecyclerView
Primero, necesita una posición de artículo
En clase Adaptador:
En
onBindViewHolder
enganchar al oyente personalizado:En MainActivity (Actividad / Fragmento) cree un campo:
En su objeto Adaptador, configure el oyente personalizado:
Segundo, crea tu menú
En res -> menú Crear un archivo que contiene su elemento de menú
context_menu_main.xml
:En MainActivity: Implemente ambos
onCreateContextMenu
yonContextItemSelected
:En tercer lugar, de vuelta a su objeto Adaptador
muestra el menú contextual.
Más información en Documentación de menús
fuente
Aquí hay una forma más sencilla de hacerlo con Kotlin que funcionó para mí. El mayor desafío es averiguar la posición del elemento que se presionó. Dentro de su adaptador, puede colocar este fragmento de código y podrá capturar la posición del elemento para el que se muestra el menú contextual; eso es todo.
fuente
He combinado mi solución con la solución de @Hardik Shah:
En la actividad tengo:
En el Adaptador tengo:
En fragmento tengo:
fuente
Quizás llego tarde a la fiesta, pero tengo una solución que funciona . He hecho una esencia para ello.
Agregar menú contextual a RecyclerView
ActivityName.java
RecyclerAdapter.java
fuente
Hola chicos, salí con una alternativa que funciona para mí. Acabo de registrar mi itemView con registerContextMenu y ViewHolder Constructor, también configuro un onLongClikcListener en la misma vista. En la implementación de onLongClick (View v), simplemente obtengo la posición en la que se hizo clic con getLayoutPosition () y la guardo en una variable de instancia (creé una clase para representar estos datos, al igual que se espera que funcione ContextMenuInfo), pero lo más importante es hacer asegúrese de devolver falso en este método. Todo lo que tienes que hacer ahora es estar en onContextItemSelected (elemento MenuItem), leer los datos que almacenas en tu variable de instancia y si es válido, continúas con tus acciones. Aquí es un fragmento.
Hago que ViewHolder implemente OnLongClickListener, pero puedes hacerlo de la forma que prefieras.
También puede configurar esto en el adaptador o en otra Vista que tenga en ViewHolder (es decir, una TextView). Lo importante es la implementación de onLongClik ().
La mejor parte es que aún puede procesar el evento LongClick devolviendo verdadero en los casos que desee, y el conextMenu no aparecerá.
Este método funciona porque registerForContextView hace que View LongClickable, y cuando llega el momento de procesar el ContextMenu, el sistema llama a performLongClick, que primero llama a una implementación onLongClick, y si devuelve falso, llama a showContextMenu.
fuente
He estado usando esta solución durante algún tiempo y me ha funcionado bastante bien.
Ahora, en su fragmento o actividad, implemente los siguientes métodos.
Finalmente, regístrese para el contextMenu en la vista de reciclaje
¡Eso debería funcionar!
fuente
A continuación, se muestra cómo puede implementar el menú contextual para RecyclerView y obtener la posición del elemento, para el que se ha seleccionado el elemento del menú contextual:
}
fuente
Una solución para aquellos que desean obtener la identificación del artículo al llamar
ContextMenu
.Si tiene un
RecyclerView
elemento con elementos como este (que contiene clicsImageView
):entonces debería recibir devoluciones de llamada de
onClickListener
.Adaptador
Fragmento
¡Advertencia!
Si usa un
ViewPager
basado en un fragmento (todas las páginas son listas similares), enfrentará un problema. Cuando anuleonContextItemSelected
para comprender qué elemento de menú se seleccionó, obtendrá una identificación de elemento de lista desde la primera página. Para superar este problema, consulte El fragmento incorrecto en ViewPager recibe la llamada onContextItemSelected .fuente
He estado luchando con esto porque Android no maneja esto bien para mí en RecyclerView, que estaba funcionando muy bien para ListView.
La pieza más difícil es que la pieza ContextMenuInfo está incrustada dentro de una Vista, que no se puede adjuntar fácilmente más que anular la Vista.
Por lo tanto, necesitará un contenedor que lo ayude a entregar la información de la posición a la Actividad.
}
Luego, en su RecyclerAdapter, cuando crea ViewHolders, necesita configurar el Wrapper como la vista raíz y registrar contextMenu en cada vista.
}
Y por último, en tu Actividad podrás hacer lo que haces habitualmente:
fuente
Lo mejor fue usar el menú contextual con la vista de reciclador si
getContextMenuInfo()
crea una vista de reciclador personalizada y anula el método y devuelve su propia instancia del objeto de información del menú contextual para que pueda buscar posiciones cuando se creó y cuando se hace clic en el menú:Eche un vistazo a esta esencia que he creado:
https://gist.github.com/resengupta/2b2e26c949b28f8973e5
fuente
Ampliando un poco algunas de las respuestas anteriores, si desea evitar definir manualmente el menú en su código en el Adaptador / ViewHolder, puede usar un PopupMenu e inflar las opciones del menú desde un archivo de recursos estándar menu.xml.
El siguiente ejemplo muestra esto, incluida la capacidad de pasar un oyente que puede implementar en su Fragmento / Actividad para responder a los clics del menú contextual.
Resumen completo aquí https://gist.github.com/brettwold/45039b7f02ce752ae0d32522a8e2ad9c
fuente
Puede pasar OnCreateContextMenuListener a ViewHolder en el enlace. Este oyente puede crear un menú personalizado para cada elemento de datos. Simplemente agregue setOnCreateContextMenuListener en su ViewHolder y llámelo durante el enlace.
}
En adaptador:
fuente
En mi caso, tuve que usar datos de mi fragmento en el
onContextItemSelected()
método. La solución con la que terminé fue pasar una instancia del fragmento a mi adaptador y registrar el elemento de vista en el soporte de vista:Luego
onCreateContextMenu()
, puede guardar el índice en una variable local:selectedViewIndex = (int)v.getTag();
y recuperarlo en
onContextItemSelected()
fuente
La primera vez que encontré este problema con los adaptadores normales, terminé creando mi propia subclase de vista personalizada y almacenando las cosas que necesitaba en ella. Realmente no me gustó esa solución y pasé mucho tiempo mirando las grandes ideas que la gente había propuesto, y decidí que no me gustaban más. Así que puse todo junto, lo sacudí por un tiempo y salí con algo nuevo que me gusta.
Comenzamos con un par de clases de servicios públicos. ContextMenuHandler es una interfaz para cualquier objeto que vaya a manejar el menú contextual. En la práctica, esta será una subclase de ViewHolder, pero en teoría podría ser casi cualquier cosa.
A continuación, se muestra una interfaz que debe implementar cualquier vista que se vaya a utilizar como hijo inmediato de un RecyclerView.
A continuación, cualquier vista que vaya a crear un menú contextual como elemento secundario de un RecylcerView debe implementar ViewWIthContextMenu. En mi caso, solo necesitaba una subclase de LinearLayout.
Y finalmente, necesitamos una clase Fragmento mejorada para interceptar las llamadas del menú contextual y redirigirlas al controlador apropiado.
Con todo esto en su lugar, la implementación final es bastante simple. El fragmento principal tiene que subclase FragmentWithContextMenu. Configura la RecylerWindow principal normalmente y se pasa a la subclase Adaptador. La subclase Adaptador se parece a
Eso es todo. Todo parece estar funcionando. Puso todas las clases de utilidad en un paquete de menú contextual separado para que pudiera haber dado los nombres de las clases que coincidían con las clases que hay en las subclases, pero pensé que sería más confuso.
fuente
Ok, basado en la respuesta de @ Flexo, pondré mPosition en orden ...
luego en onContextItemSelected utilizo
Y todo funciona bien, obtengo la posición de la matriz fácilmente
fuente