Desde https://developer.android.com/preview/material/ui-widgets.html
Cuando creamos RecyclerView.Adapter
tenemos que especificar ViewHolder
que se unirá con el adaptador.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private String[] mDataset;
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.some_layout, parent, false);
//findViewById...
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
}
@Override
public int getItemCount() {
return mDataset.length;
}
}
Entonces, ¿es posible crear RecyclerView
con múltiples tipos de vista?
Respuestas:
Si es posible. Simplemente implemente getItemViewType () y cuide el
viewType
parámetro enonCreateViewHolder()
.Entonces haces algo como:
fuente
optionMenuItem
. ¿Como es posible? @AntonSavinSi los diseños para los tipos de vista son pocos y las lógicas de enlace son simples, siga la solución de Anton.
Pero el código será complicado si necesita administrar diseños complejos y lógicas de enlace.
Creo que la siguiente solución será útil para alguien que necesite manejar tipos de vista complejos.
Clase base de DataBinder
Las funciones necesarias para definir en esta clase son bastante similares a las de la clase de adaptador al crear el tipo de vista única.
Para cada tipo de vista, cree la clase extendiendo este DataBinder.
Clase DataBinder de muestra
Para administrar las clases de DataBinder, cree una clase de adaptador.
Clase Base DataBindAdapter
Cree la clase extendiendo esta clase base, y luego instancia las clases de DataBinder y anule los métodos abstractos
getItemCount
Devuelve el recuento total de elementos de DataBinders
getItemViewType
Define la lógica de mapeo entre la posición del adaptador y el tipo de vista.
getDataBinder
Devuelve la instancia de DataBinder en función del tipo de vista
getPosition
Define la lógica de conversión a la posición del adaptador desde la posición en el DataBinder especificado
getBinderPosition
Define la lógica de conversión a la posición en el DataBinder desde la posición del adaptador
Espero que esta solución sea útil.
Dejé una solución más detallada y muestras en GitHub, así que consulte el siguiente enlace si lo necesita.
https://github.com/yqritc/RecyclerView-MultipleViewTypesAdapter
fuente
public class DataBinder<T extends RecyclerView.ViewHolder>
¿alguien puede decirme cómo<T someClass>
se llama, para que pueda googlear si obtengo el término Además, cuando digoabstract public class DataBinder<T extends RecyclerView.ViewHolder>
¿eso significa que esta clase es de tipoViewHolder
, por lo que en consecuencia cada clase que amplíe esta clase será de tipoviewHolder
? ¿Esa es la idea?El siguiente no es un pseudocódigo y lo he probado y me ha funcionado.
Quería crear una vista de encabezado en mi vista de reciclador y luego mostrar una lista de imágenes debajo del encabezado en el que el usuario puede hacer clic.
Utilicé algunos modificadores en mi código, no sé si esa es la forma más eficiente de hacerlo, así que no dude en dar sus comentarios:
fuente
Sí, es posible.
Escriba un titular de vista genérico:
luego cree sus titulares de vista y haga que extiendan el GenericViewHolder. Por ejemplo, este:
entonces la clase RecyclerView.Adapter se verá así:
fuente
Crear ViewHolder diferente para un diseño diferente
RecyclerView puede tener cualquier cantidad de visualizadores que desee, pero para una mejor legibilidad, veamos cómo crear uno con dos ViewHolders.
public int getItemViewType(int position)
onCreateViewHolder()
método ViewType enonBindViewHolder()
método itemViewType enAquí hay un pequeño fragmento de código
getItemViewType (int position) es la clave
En mi opinión, el punto de partida para crear este tipo de recyclerView es el conocimiento de este método. Dado que este método es opcional para anular, por lo tanto, no es visible en la clase RecylerView de forma predeterminada, lo que a su vez hace que muchos desarrolladores (incluido yo) se pregunten dónde comenzar. Una vez que sepa que este método existe, crear tal RecyclerView sería un juego de niños.
Enlaces relevantes:
Echa un vistazo al proyecto donde he implementado esto
fuente
Sí, es posible. En su adaptador getItemViewType Layout así ...
para enlace de referencia: https://www.journaldev.com/12372/android-recyclerview-example
fuente
siguiendo la solución de Anton, invente esto
ViewHolder
que contenga / maneje / delegue diferentes tipos de diseños. Pero no estoy seguro de si el nuevo diseño de reemplazo funcionaría cuando la vista de reciclajeViewHolder
no sea el tipo de datos en rollo.Básicamente,
onCreateViewHolder(ViewGroup parent, int viewType)
solo se llama cuando se necesita un nuevo diseño de vista;getItemViewType(int position)
será llamado para elviewType
;onBindViewHolder(ViewHolder holder, int position)
siempre se llama al reciclar la vista (se introducen nuevos datos y se intenta mostrar con esoViewHolder
).Entonces, cuando
onBindViewHolder
se llama, debe colocar el diseño de vista correcto y actualizar elViewHolder
.¿Es la forma correcta de reemplazar el diseño de la vista para que
ViewHolder
se traiga, o algún problema? Agradezco cualquier comentario!Editar: ViewHolder tiene miembro mItemViewType para mantener la vista
Editar: parece que en onBindViewHolder (soporte de ViewHolder, posición int), el ViewHolder pasado ha sido recogido (o creado) por getItemViewType (posición int) para asegurarse de que coincida, por lo que es posible que no tenga que preocuparse de que ViewHolder's tipo no coincide con el tipo de datos [posición]. ¿Alguien sabe más cómo se recoge el ViewHolder en onBindViewHolder ()?
Editar: Parece que el reciclaje
ViewHolder
se selecciona por tipo, por lo que no hay guerrero allí.Editar: http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/ responde a esta pregunta.
Obtiene el reciclaje
ViewHolder
como:o cree uno nuevo si no encuentra el reciclaje
ViewHolder
del tipo correcto.fuente
Tengo una mejor solución que permite crear múltiples tipos de vistas de forma declarativa y segura. Está escrito en Kotlin que por cierto es realmente agradable.
Soportes de vista simple para todos los tipos de vista requeridos
Hay una abstracción del elemento de datos del adaptador. Tenga en cuenta que un tipo de vista está representado por un hashCode de clase de titular de vista particular (KClass en Kotlin)
Solo
bindViewHolder
debe anularse en las clases de elementos de adaptador de hormigón (tipo seguro)La lista de dichos
AdapterItemMedium
objetos es una fuente de datos para el adaptador que realmente acepta,List<AdapterItem>
ver a continuación.Parte importante de esta solución es una fábrica de soporte de vistas que proporcionará nuevas instancias de un ViewHolder específico
Y la clase de adaptador simple se ve así
Solo 3 pasos para crear un nuevo tipo de vista:
ViewHolderProvider
Aquí hay un ejemplo de este concepto: android-drawer-template Va aún más lejos: tipo de vista que actúa como un componente giratorio, elementos de adaptador seleccionables.
fuente
Es muy simple y directo.
Simplemente anule el método getItemViewType () en su adaptador. Sobre la base de los datos, devuelva diferentes valores de itemViewType. Por ejemplo, considere un objeto de tipo Persona con un miembro isMale, si isMale es verdadero, devuelve 1 e isMale es falso, devuelve 2 en el método getItemViewType () .
Ahora llega al createViewHolder (ViewGroup parent, int viewType) , sobre la base de diferentes viewType, puede inflar los diferentes archivos de diseño. como el siguiente
en onBindViewHolder (soporte VH, posición int) verifique dónde está la instancia del titular
AdapterFemaleViewHolder
oAdapterMaleViewHolder
porinstanceof
y, en consecuencia, asigne los valores.ViewHolder puede ser así
fuente
Aunque la respuesta seleccionada es correcta, solo quiero elaborarla más. Encontré aquí un adaptador personalizado útil para múltiples tipos de vista en RecyclerView . Su versión de Kotlin está aquí .
Adaptador personalizado está siguiendo
fuente
Recomiendo esta biblioteca de Hannes Dorfmann. Encapsula toda la lógica relacionada con un tipo de vista particular en un objeto separado llamado "AdapterDelegate". https://github.com/sockeqwe/AdapterDelegates
fuente
En realidad, me gustaría mejorar la respuesta de Anton .
Como
getItemViewType(int position)
devuelve un valor entero, puede devolver el ID de recurso de diseño que necesitaría para inflar. De esa manera guardarías algo de lógica en elonCreateViewHolder(ViewGroup parent, int viewType)
método.Además, no sugeriría hacer cálculos intensivos
getItemCount()
ya que esa función en particular se llama al menos 5 veces al representar la lista, así como al representar cada elemento más allá de los elementos visibles. Lamentablemente, dado que elnotifyDatasetChanged()
método es final, realmente no puede anularlo, pero puede llamarlo desde otra función dentro del adaptador.fuente
Note: Integers must be in the range 0 to getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPE can also be returned.
así que es mejor escribir un poco más de código y no usar hacks.Puede usar la biblioteca: https://github.com/vivchar/RendererRecyclerViewAdapter
``
Para cada elemento, debe implementar un ViewRenderer, ViewHolder, SomeModel:
ViewHolder: es un titular de vista simple de vista de reciclador.
SomeModel: es su modelo con
ItemModel
interfazPara más detalles puedes mirar documentaciones.
fuente
La implementación de tipos de vista se vuelve más fácil con kotlin, aquí hay una muestra con esta biblioteca ligera https://github.com/Link184/KidAdapter
fuente
Puede tratar multiples tipos
RecyclerAdapter
de vista haciendo quegetItemViewType()
devuelva elviewType
valor esperado para esa posiciónPreparé una
MultipleViewTypeAdapter
lista de MCQ para la construcción de exámenes que pueden arrojar una pregunta que puede tener 2 o más respuestas válidas (opciones de casilla de verificación) y una sola pregunta de respuesta (opciones de botón de radio).Para esto obtengo el tipo de Pregunta de la respuesta API y lo usé para decidir qué vista tengo que mostrar para esa pregunta.
Puede evitar múltiples rellenos de datos basados en viewHolder condicionalmente
onBindViewHolder()
asignando los mismos identificadores para las vistas similares en viewHolders que difieren en su posición.fuente
Si desea usarlo junto con el enlace de datos de Android, consulte https://github.com/evant/binding-collection-adapter : es, con mucho, la mejor solución para los tipos de vistas múltiples
RecyclerView
que he visto.puedes usarlo como
y luego en el diseño donde está la lista
los elementos de su lista deben implementar una
BaseListItem
interfaz similar a estay la vista del elemento debería verse así
Donde
YourListItem
implementaBaseListItem
Espero que ayude a alguien.
fuente
primero debes crear 2 xml de diseño. después de eso, dentro del adaptador de vista de reciclaje TYPE_CALL y TYPE_EMAIL hay dos valores estáticos con 1 y 2 respectivamente en la clase de adaptador.
ahora Defina dos valores estáticos en el nivel de clase Adaptador de vista de Reciclador, por ejemplo: private static int TYPE_CALL = 1; private static int TYPE_EMAIL = 2;
Ahora cree un titular de vista con múltiples vistas como esta:
Ahora codifique como se muestra a continuación en el método onCreateViewHolder y onBindViewHolder en el adaptador de la vista de reciclaje:
fuente