Depuis https://developer.android.com/preview/material/ui-widgets.html
Lorsque nous créons, RecyclerView.Adapter
nous devons spécifier ce ViewHolder
qui sera lié à l'adaptateur.
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;
}
}
Alors, est-il possible de créer RecyclerView
avec plusieurs types de vues?
Réponses:
Oui c'est possible. Implémentez simplement getItemViewType () et prenez soin du
viewType
paramètre dansonCreateViewHolder()
.Vous faites donc quelque chose comme:
la source
optionMenuItem
. Comment c'est possible? @AntonSavinSi les dispositions pour les types de vue sont rares et que les logiques de liaison sont simples, suivez la solution d'Anton.
Mais le code sera compliqué si vous devez gérer les dispositions complexes et les logiques de liaison.
Je crois que la solution suivante sera utile pour quelqu'un qui doit gérer des types de vues complexes.
Classe DataBinder de base
Les fonctions nécessaires pour définir dans cette classe sont à peu près les mêmes que la classe d'adaptateur lors de la création du type de vue unique.
Pour chaque type de vue, créez la classe en étendant ce DataBinder.
Exemple de classe DataBinder
Afin de gérer les classes DataBinder, créez une classe d'adaptateur.
Classe DataBindAdapter de base
Créez la classe en étendant cette classe de base, puis instanciez les classes DataBinder et remplacez les méthodes abstraites
getItemCount
Renvoie le nombre total d'éléments de DataBinders
getItemViewType
Définissez la logique de mappage entre la position de l'adaptateur et le type de vue.
getDataBinder
Renvoie l'instance DataBinder en fonction du type de vue
getPosition
Définissez la logique de conversion à la position de l'adaptateur à partir de la position dans le DataBinder spécifié
getBinderPosition
Définissez la logique de conversion à la position dans le DataBinder à partir de la position de l'adaptateur
J'espère que cette solution vous sera utile.
J'ai laissé plus de détails et de solutions dans GitHub, veuillez donc consulter le lien suivant si vous en avez besoin.
https://github.com/yqritc/RecyclerView-MultipleViewTypesAdapter
la source
public class DataBinder<T extends RecyclerView.ViewHolder>
quelqu'un peut-il me dire ce<T someClass>
qu'on appelle, donc je peux google si j'obtiens le terme. Aussi quand je disabstract public class DataBinder<T extends RecyclerView.ViewHolder>
cela signifie-t-il que cette classe est de typeViewHolder
, donc en résultat chaque classe qui étend cette classe sera de typeviewHolder
est-ce l'idée?Ce qui suit n'est pas un pseudocode et je l'ai testé et cela a fonctionné pour moi.
Je voulais créer une vue de tête dans ma vue de recyclage, puis afficher une liste d'images sous l'en-tête sur laquelle l'utilisateur peut cliquer.
J'ai utilisé quelques commutateurs dans mon code, je ne sais pas si c'est le moyen le plus efficace de le faire, alors n'hésitez pas à donner vos commentaires:
la source
Oui c'est possible.
Écrivez un support de vue générique:
puis créez vos supports de vue et faites-les étendre le GenericViewHolder. Par exemple, celui-ci:
alors la classe RecyclerView.Adapter ressemblera à celle-ci:
la source
Créer un ViewHolder différent pour une disposition différente
RecyclerView peut avoir autant de vues que vous le souhaitez, mais pour une meilleure lisibilité, voyons comment en créer une avec deux ViewHolders.
public int getItemViewType(int position)
onCreateViewHolder()
méthode ViewType inonBindViewHolder()
méthode itemViewType dansVoici un petit extrait de code
getItemViewType (int position) est la clé
À mon avis, le point de départ pour créer ce type de recyclerView est la connaissance de cette méthode. Étant donné que cette méthode est facultative pour remplacer, elle n'est donc pas visible par défaut dans la classe RecylerView, ce qui fait que de nombreux développeurs (dont moi) se demandent par où commencer. Une fois que vous savez que cette méthode existe, la création d'un tel RecyclerView serait un jeu d'enfant.
Liens pertinents:
Découvrez le projet où j'ai mis en œuvre ce
la source
Oui c'est possible. Dans votre adaptateur getItemViewType Layout comme ceci ....
pour le lien de référence: https://www.journaldev.com/12372/android-recyclerview-example
la source
à la suite de la solution d'Anton, proposez-en une
ViewHolder
qui contient / gère / délègue différents types de dispositions. Mais je ne sais pas si la nouvelle disposition de remplacement fonctionnerait lorsque la vue de recyclageViewHolder
n'est pas le type de données.Donc, en gros,
onCreateViewHolder(ViewGroup parent, int viewType)
n'est appelé que lorsqu'une nouvelle disposition de vue est nécessaire;getItemViewType(int position)
sera appelé pour leviewType
;onBindViewHolder(ViewHolder holder, int position)
est toujours appelé lors du recyclage de la vue (de nouvelles données sont introduites et essaient de s'afficher avecViewHolder
).Donc, quand
onBindViewHolder
est appelé, il doit mettre la bonne vue et mettre à jour leViewHolder
.La façon de remplacer la disposition de la vue pour cela
ViewHolder
doit-elle être correcte ou un problème? Appréciez tout commentaire!Modifier: ViewHolder a un membre mItemViewType pour contenir la vue
Edit: ressemble à onBindViewHolder (titulaire de ViewHolder, position int) le ViewHolder transmis a été récupéré (ou créé) en regardant getItemViewType (position int) pour vous assurer qu'il s'agit d'une correspondance, donc vous n'aurez peut-être pas à vous inquiéter que ViewHolder soit type ne correspond pas au type de données [position]. Est-ce que quelqu'un sait plus comment le ViewHolder dans onBindViewHolder () est récupéré?
Edit: On dirait que le recyclage
ViewHolder
est choisi par type, donc pas de guerrier là-bas.Edit: http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/ répond à cette question.
Il obtient le recyclage
ViewHolder
comme:ou en créer un nouveau si ce n'est pas trouver le recyclage
ViewHolder
du bon type.la source
J'ai une meilleure solution qui permet de créer plusieurs types de vues de manière déclarative et sécurisée. C'est écrit en Kotlin, ce qui est vraiment sympa.
Porte-vues simples pour tous les types de vue requis
Il existe une abstraction de l'élément de données de l'adaptateur. Notez qu'un type de vue est représenté par un hashCode d'une classe de détenteur de vue particulière (KClass dans Kotlin)
Ne
bindViewHolder
doit être remplacé que dans les classes d'éléments d'adaptateur en béton (type de manière sûre)La liste de ces
AdapterItemMedium
objets est une source de données pour l'adaptateur qui accepte réellementList<AdapterItem>
voir ci-dessous.Une partie importante de cette solution est une fabrique de supports de vues qui fournira de nouvelles instances d'un ViewHolder spécifique
Et la classe d'adaptateur simple ressemble à ceci
Seulement 3 étapes pour créer un nouveau type de vue:
ViewHolderProvider
Voici un exemple de ce concept: modèle de tiroir android Il va encore plus loin - voir le type qui agit comme un composant spinner, des éléments d'adaptateur sélectionnables.
la source
C'est très simple et direct.
Remplacez simplement la méthode getItemViewType () dans votre adaptateur. Sur la base des données, renvoyer différentes valeurs itemViewType. Par exemple, considérons un objet de type Personne avec un membre isMale, si isMale est vrai, retourne 1 et isMale est faux, retourne 2 dans la méthode getItemViewType () .
Arrive maintenant au createViewHolder (parent ViewGroup, int viewType) , sur la base de différents viewType, vous pouvez gonfler les différents fichiers de disposition. comme le suivant
dans onBindViewHolder (support VH, position int), vérifiez où le support est une instance de
AdapterFemaleViewHolder
ouAdapterMaleViewHolder
parinstanceof
et affectez en conséquence les valeurs.ViewHolder Peut être comme ça
la source
Bien que la réponse choisie soit correcte, je veux juste la développer davantage. J'ai trouvé ici un adaptateur personnalisé utile pour plusieurs types de vues dans RecyclerView . Sa version Kotlin est ici .
L'adaptateur personnalisé suit
la source
Je recommande cette bibliothèque de Hannes Dorfmann. Il encapsule toute la logique liée à un type de vue particulier dans un objet séparé appelé "AdapterDelegate". https://github.com/sockeqwe/AdapterDelegates
la source
En fait, j'aimerais améliorer la réponse d'Anton .
Puisque
getItemViewType(int position)
renvoie une valeur entière, vous pouvez renvoyer l'ID de ressource de mise en page dont vous avez besoin pour gonfler. De cette façon, vous enregistrez un peu de logiqueonCreateViewHolder(ViewGroup parent, int viewType)
méthode.Aussi, je ne suggérerais pas de faire des calculs intensifs dans
getItemCount()
car cette fonction particulière est appelée au moins 5 fois lors du rendu de la liste, ainsi que lors du rendu de chaque élément au-delà des éléments visibles. Malheureusement, puisque lanotifyDatasetChanged()
méthode est finale, vous ne pouvez pas vraiment la remplacer, mais vous pouvez l'appeler à partir d'une autre fonction de l'adaptateur.la source
Note: Integers must be in the range 0 to getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPE can also be returned.
Il est donc préférable d'écrire un peu plus de code et de ne pas utiliser de hacks.Vous pouvez utiliser la bibliothèque: https://github.com/vivchar/RendererRecyclerViewAdapter
"
Pour chaque élément, vous devez implémenter un ViewRenderer, ViewHolder, SomeModel:
ViewHolder - c'est un simple support de vue de la vue du recycleur.
SomeModel - c'est votre modèle avec
ItemModel
interfacePour plus de détails, vous pouvez consulter les documentations.
la source
La mise en œuvre des types de vues devient plus facile avec kotlin, voici un exemple avec cette bibliothèque légère https://github.com/Link184/KidAdapter
la source
Vous pouvez traiter plusieurs ViewTypes
RecyclerAdapter
en faisantgetItemViewType()
retourner le résultat attenduviewType
valeur pour cette positionJ'ai préparé une
MultipleViewTypeAdapter
liste pour la construction de QCM pour les examens qui peuvent jeter une question qui peut avoir 2 réponses valides ou plus (options de case à cocher) et une question à réponse unique (options de radiobutton).Pour cela, je reçois le type de question de la réponse de l'API et je l'ai utilisé pour décider quelle vue je dois montrer pour cette question.
Vous pouvez éviter plusieurs remplissages de données viewHolder conditionnels en
onBindViewHolder()
affectant les mêmes identifiants pour les vues similaires parmi les viewHolders qui diffèrent dans leur positionnement.la source
Si vous souhaitez l'utiliser en conjonction avec Android Data Binding, regardez dans https://github.com/evant/binding-collection-adapter - c'est de loin la meilleure solution pour les types de vues multiples
RecyclerView
j'ai même vus.vous pouvez l'utiliser comme
puis dans la mise en page où la liste est
vos éléments de liste doivent implémenter une
BaseListItem
interface qui ressemble à ceciet la vue des éléments devrait ressembler à ceci
Où
YourListItem
met en œuvreBaseListItem
J'espère que cela aidera quelqu'un.
la source
vous devez d'abord créer 2 xml de mise en page. après cela, à l'intérieur de l'adaptateur de vue de recyclage, TYPE_CALL et TYPE_EMAIL sont deux valeurs statiques avec respectivement 1 et 2 dans la classe d'adaptateur.
maintenant Définissez deux valeurs statiques au niveau de la classe Adaptateur de vue Recycler par exemple: private static int TYPE_CALL = 1; int statique statique TYPE_EMAIL = 2;
Créez maintenant un support de vue avec plusieurs vues comme ceci:
Maintenant, codez comme ci-dessous dans la méthode onCreateViewHolder et onBindViewHolder dans l'adaptateur de recyclage:
la source