Estaba explorando RecyclerViewy me sorprendió ver queRecyclerView no tiene onItemClickListener().
Tengo dos preguntas.
Pregunta principal
Quiero saber por qué Google eliminó onItemClickListener() ?
¿Hay un problema de rendimiento o algo más?
Pregunta secundaria
Resolví mi problema escribiendo onClickmi RecyclerView.Adapter:
public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
    public TextView txtViewTitle;
    public ImageView imgViewIcon;
    public ViewHolder(View itemLayoutView) {
        super(itemLayoutView);
        txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
        imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
    }
    @Override
    public void onClick(View v) {
    }
}
¿Está bien / hay alguna manera mejor?
                    
                        java
                                android
                                android-recyclerview
                                
                    
                    
                        Tarun Varshney
fuente
                
                fuente

QUESTIONRespuestas:
tl; dr 2016 Use RxJava y PublishSubject para exponer un Observable para los clics.
Publicación original:
Desde la introducción de
ListView,onItemClickListenerha sido problemático. En el momento en que tiene un escucha de clics para cualquiera de los elementos internos, la devolución de llamada no se activará, pero no se notificó ni se documentó bien (si es que lo hizo), por lo que hubo mucha confusión y SO preguntas al respecto.Dado que
RecyclerViewva un paso más allá y no tiene el concepto de una fila / columna, sino más bien una cantidad arbitraria de niños, han delegado el onClick a cada uno de ellos o a la implementación del programador.Piense
Recyclerviewno como unListViewreemplazo 1: 1 sino como un componente más flexible para casos de uso complejos. Y como usted dice, su solución es lo que Google esperaba de usted. Ahora tiene un adaptador que puede delegar onClick a una interfaz pasada en el constructor, que es el patrón correcto para ambosListViewyRecyclerview.y luego en tu adaptador
Ahora mire ese último fragmento de código:
onCreateViewHolder(ViewGroup parent, int viewType)la firma ya sugiere diferentes tipos de vistas. Para cada uno de ellos, también necesitará un marcador de vista diferente, y posteriormente cada uno de ellos puede tener un conjunto diferente de clics. O simplemente puede crear un marcador de vista genérico que tome cualquier vista y unaonClickListenery se aplique en consecuencia. O delegue un nivel al orquestador para que varios fragmentos / actividades tengan la misma lista con un comportamiento de clic diferente. Nuevamente, toda la flexibilidad está de su lado.Es un componente realmente necesario y bastante cercano a lo que
ListVieweran nuestras implementaciones y mejoras internas hasta ahora. Es bueno que Google finalmente lo reconozca.fuente
onBindViewHolder(holder, position), que es donde se supone que debe llenarse la información.getPosition()está en desuso "Este método está en desuso porque su significado es ambiguo debido al manejo asíncrono * de las actualizaciones del adaptador. Utilice {@link #getLayoutPosition ()} o * {@link #getAdapterPosition ()} dependiendo de su caso de uso. "viewHolder.getPosition();Por qué el RecyclerView no tiene
onItemClickListenerlos
RecyclerViewes una caja de herramientas, en contraste con el anteriorListView, tiene menos características incorporadas y más flexibilidad. LaonItemClickListenerno es la única característica que se elimina de ListView. Pero tiene muchos oyentes y un método para extenderlo a su gusto, es mucho más poderoso en las manos adecuadas;).En mi opinión, la característica más compleja eliminada en
RecyclerViewes el Desplazamiento rápido . La mayoría de las otras características se pueden volver a implementar fácilmente.Si quieres saber qué otras características interesantes
RecyclerViewagregaron, lea esta respuesta a otra pregunta.Memoria eficiente: solución integrada para onItemClickListener
Esta solución ha sido propuesta por Hugo Visser , un Android GDE, justo después de
RecyclerViewsu lanzamiento. Puso a su disposición una clase sin licencia para que simplemente ingrese su código y lo use.Muestra parte de la versatilidad introducida
RecyclerViewal hacer uso deRecyclerView.OnChildAttachStateChangeListener.Edición 2019 : versión kotlin de mí, java one, de Hugo Visser, que se muestra a continuación
Kotlin / Java
Crea un archivo
values/ids.xmly pon esto en él:luego agregue el siguiente código a su fuente
Kotlin
Uso:
(también admite hacer clic en un elemento largo y ver a continuación otra característica que he agregado).
implementación (mi adaptación al código Java de Hugo Visser):
(ver abajo también necesita agregar un archivo XML)
Característica adicional de la versión de Kotlin
A veces no desea que se pueda hacer clic en todos los elementos de RecyclerView.
Para manejar esto, he introducido la
ItemClickSupportViewHolderinterfaz que puede usar en suViewHolderpara controlar qué elemento se puede hacer clic.Ejemplo:
Java
Uso:
(también admite clics largos en elementos)
Implementación (comentarios añadidos por mí):
Cómo funciona (por qué es eficiente)
Esta clase funciona adjuntando un
RecyclerView.OnChildAttachStateChangeListeneraRecyclerView. Este oyente recibe una notificación cada vez que un niño está conectado o desconectado delRecyclerView. El código lo utiliza para agregar un oyente de toque / clic largo a la vista. Ese oyente preguntaRecyclerViewporRecyclerView.ViewHoldercual contiene la posición.Esto es más eficiente que otras soluciones porque evita crear múltiples oyentes para cada vista y sigue destruyéndolos mientras los
RecyclerViewse desplaza.También puede adaptar el código para devolverle el soporte si necesita más.
Comentario final
Tenga en cuenta que está COMPLETAMENTE bien manejarlo en su adaptador configurando en cada vista de su lista un escucha de clics, como otra respuesta propuesta.
Simplemente no es lo más eficiente (crea un nuevo oyente cada vez que reutiliza una vista) pero funciona y en la mayoría de los casos no es un problema.
También es un poco en contra de la separación de las preocupaciones porque no es realmente el trabajo del adaptador delegar eventos de clic.
fuente
addTo()yremoveFrom(). La instancia está asociada a la etiqueta de vista de reciclaje y muere con ella o cuando se elimina manualmente.onCreateViewHoldery eso es todo.RecyclerView.Me gusta de esta manera y lo estoy usando
Dentro
Poner
Y crea esta clase donde quieras
He leído antes que hay una mejor manera, pero me gusta que sea fácil y no complicado
fuente
MyOnClickListeneren una variable de instancia, porquenewrecyclerViewa MyOnClickListener?Android Recyclerview Con
onItemClickListener, por qué no podemos intentarlo, esto funciona comoListViewsolo.Fuente: Enlace
Y configure esto en RecyclerView:
fuente
SwipeRefreshLayoutGracias a @marmor, actualicé mi respuesta.
Creo que es una buena solución para manejar el onClick () en el constructor de la clase ViewHolder y pasarlo a la clase principal a través de OnItemClickListener interfaz .
MyAdapter.java
Uso del adaptador en otras clases:
MyFragment.java
fuente
onBindViewHolder()se llama muchas veces para la misma vista al desplazarse. Incluso crear uno soloOnClickListenerno ayudará porque restableceráOnClickListenercada vez queonBindViewHolder()se llama. Ver en su lugar la solución @ MLProgrammer-CiM.MyAdapter.ViewHolder vh = new ViewHolder(v, new MyAdapter.ViewHolder.IMyViewHolderClicks() ...., puede crear un solo escucha para todas las vistas.Los chicos usan este código en su actividad principal. Método muy eficiente
Aquí está tu clase de adaptador.
Después de esto, obtendrá este método de anulación en su actividad.
fuente
> ¿En qué se diferencia RecyclerView de Listview?
Una diferencia es que hay una
LayoutManagerclase con RecyclerView por la cual puede administrar sus meRecyclerViewgusta-Al igual que para el desplazamiento horizontal para RecyclerView-
fuente
Seguimiento de la excelente solución RxJava de MLProgrammer-CiM
Consumir / observar clics
RxJava 2. +
Modifique el tl original ; dr como:
PublishSubject#asObservable()fue removido. Simplemente devuelva elPublishSubjectque es unObservable.fuente
Cómo poner todo junto ejemplo ...
Tipos de ViewHolder
fuente
Hasta donde entiendo la respuesta MLProgrammer-CiM , simplemente es posible hacer esto:
fuente
Después de leer la respuesta de @ MLProgrammer-CiM , aquí está mi código:
fuente
getAdapterPositionpuede volver-1por "ninguna posición".Lo he hecho de esta manera, es muy simple:
Simplemente agregue 1 línea para la posición Clickcy RecyclerView :
Código completo para la clase ViewHolder :
Espero que esto te ayudará.
fuente
getAdapterPositionlugar degetLayoutPosition. Protéjase contra-1.Utilizo este método para iniciar una intención desde RecyclerView:
fuente
onBindViewHolder(...)no se llama después de losnotify()métodos. Por lo tanto, puede obtener una posición de clic incorrecta en algunas situaciones.RecyclerView no tiene un
onItemClickListenerporque RecyclerView es responsable de reciclar las vistas (¡sorpresa!), Por lo que es responsabilidad de la vista que se recicla manejar los eventos de clics que recibe.En realidad, esto hace que sea mucho más fácil de usar, especialmente si tenía elementos en los que se puede hacer clic en varios lugares.
De todos modos, detectar el clic en un elemento RecyclerView es muy fácil. Todo lo que necesita hacer es definir una interfaz (si no está usando Kotlin, en cuyo caso simplemente pasa una lambda):
Mismo código en Kotlin:
Cosa que NO necesitas hacer:
1.) no necesita interceptar eventos táctiles manualmente
2.) no necesita perder el tiempo con los oyentes adjuntos de cambio de estado
3.) no necesita PublishSubject / PublishRelay de RxJava
Simplemente use un oyente de clics.
fuente
Vea mi enfoque sobre esto:
Primero declara una interfaz como esta:
Luego cree el adaptador:
Y ahora veamos cómo integrar esto desde un fragmento:
fuente
Si desea agregar onClick () a la vista secundaria de elementos, por ejemplo, un botón en el elemento, descubrí que puede hacerlo fácilmente en onCreateViewHolder () de su propio RecyclerView.Adapter así:
No sé si es una buena manera, pero funciona bien. Si alguien tiene una idea mejor, ¡me alegra contarme y corregir mi respuesta! :)
fuente
Aquí hay una manera de implementarlo con bastante facilidad si tiene una lista de POJO y desea recuperar uno al hacer clic desde fuera del adaptador.
En su adaptador, cree un escucha para los eventos de clic y un método para configurarlo:
}
En su ViewHolder, implemente onClickListener y cree un miembro de la clase para almacenar temporalmente el POJO que presenta la vista, de esa manera (este es un ejemplo, sería mejor crear un setter):
De vuelta en su adaptador, configure el POJO actual cuando el ViewHolder esté vinculado (o sea nulo si la vista actual no tiene uno):
Eso es todo, ahora puedes usarlo así desde tu fragmento / actividad:
fuente
mMyAdapter.setOnItemClickListener(MyAdapter.OnItemClickListener() {});sí tu puedes
fuente
Aquí puede manejar múltiples clics en el código de abajo y es muy eficiente
fuente
itemView.Modificó mi comentario ...
fuente
getAdapterPosition().Marque este en el que he implementado todas las cosas de manera adecuada
Clase RecyclerViewHolder
Adaptador
La interfaz
fuente
Esto funcionó para mí:
fuente
setOnClickListener(holder)enonBindViewHolder(). Porque onBindViewHolder (...) no se llama después de los métodos notify (). Entonces, puede obtener una posición de clic incorrecta en algunas situaciones.onCreateViewHolder.Acceda a la
mainViewderowLayout(cell)ustedRecyclerViewy en suOnBindViewHolderescritura escriba este código:fuente
En lugar de implementar la interfaz View.OnClickListener dentro del soporte de la vista o crear e interactuar e implementar la interfaz en su actividad ... Usé este código para la implementación simple de OnClickListener.
fuente
Vista interior titular
Inside OnBindViewHolder ()
Y hágamelo saber, ¿tiene alguna pregunta sobre esta solución?
fuente
onCreateViewHolderpara un mejor rendimiento, pero luego debe obtener la posición usandogetAdapterPosition()(y protegerse contra-1)fuente
use PlaceHolderView
fuente
Escribí una biblioteca para manejar el evento de clic de elemento de vista de reciclador de Android. Puede encontrar todo el tutorial en https://github.com/ChathuraHettiarachchi/RecycleClick
o para manejar el artículo, presione prolongadamente, puede usar
fuente
La animación de la vista de reciclaje no se ha probado, la otra es normal. Creo que ha sido optimizado al máximo. La interfaz tiene otros usos, puede ignorar temporalmente.
Esta es la interfaz
Esto es una clase abstracta
Solo lo necesitas
fuente
Ejemplo con getTag () / setTag () y escucha de un solo clic para todo el adaptador:
La TAG_POSICIÓN definida en el archivo tags.xml como
fuente