Estaba explorando RecyclerView
y 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 onClick
mi 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
QUESTION
Respuestas:
tl; dr 2016 Use RxJava y PublishSubject para exponer un Observable para los clics.
Publicación original:
Desde la introducción de
ListView
,onItemClickListener
ha 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
RecyclerView
va 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
Recyclerview
no como unListView
reemplazo 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 ambosListView
yRecyclerview
.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 unaonClickListener
y 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
ListView
eran 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
onItemClickListener
los
RecyclerView
es una caja de herramientas, en contraste con el anteriorListView
, tiene menos características incorporadas y más flexibilidad. LaonItemClickListener
no 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
RecyclerView
es 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
RecyclerView
agregaron, 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
RecyclerView
su 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
RecyclerView
al 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.xml
y 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
ItemClickSupportViewHolder
interfaz que puede usar en suViewHolder
para 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.OnChildAttachStateChangeListener
aRecyclerView
. 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 preguntaRecyclerView
porRecyclerView.ViewHolder
cual 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
RecyclerView
se 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.onCreateViewHolder
y 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
MyOnClickListener
en una variable de instancia, porquenew
recyclerView
a MyOnClickListener?Android Recyclerview Con
onItemClickListener
, por qué no podemos intentarlo, esto funciona comoListView
solo.Fuente: Enlace
Y configure esto en RecyclerView:
fuente
SwipeRefreshLayout
Gracias 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 soloOnClickListener
no ayudará porque restableceráOnClickListener
cada 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
LayoutManager
clase con RecyclerView por la cual puede administrar sus meRecyclerView
gusta-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 elPublishSubject
que 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
getAdapterPosition
puede volver-1
por "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
getAdapterPosition
lugar 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
onItemClickListener
porque 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
mainView
derowLayout(cell)
ustedRecyclerView
y en suOnBindViewHolder
escritura 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
onCreateViewHolder
para 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