Je souhaite corriger mes vues d'en-tête en haut de l'écran comme dans l'image ci-dessous et sans utiliser de bibliothèques externes.
Dans mon cas, je ne veux pas le faire par ordre alphabétique. J'ai deux types de vues différents (en-tête et normal). Je veux seulement fixer le haut, le dernier en-tête.
android
header
android-recyclerview
sticky
Jaume Colom
la source
la source
Réponses:
Ici, je vais vous expliquer comment le faire sans bibliothèque externe. Ce sera un très long post, alors préparez-vous.
Tout d'abord, permettez-moi de remercier @ tim.paetz dont le message m'a inspiré à entreprendre un voyage d'implémentation de mes propres en-têtes collants en utilisant
ItemDecoration
s. J'ai emprunté certaines parties de son code dans mon implémentation.Comme vous l'avez déjà fait l' expérience, si vous essayez de le faire vous - même, il est très difficile de trouver une bonne explication de COMMENT faire réellement avec la
ItemDecoration
technique. Je veux dire, quelles sont les étapes? Quelle est la logique derrière cela? Comment faire coller l'en-tête en haut de la liste? Ne pas connaître les réponses à ces questions est ce qui incite les autres à utiliser des bibliothèques externes, alors que le faire soi-même avec l'utilisation deItemDecoration
est assez facile.Conditions initiales
list
des éléments de type différent (pas dans un sens de "types Java", mais dans un sens de types "en-tête / élément").list
doit être un élément d'en-tête.Ici, je fournit le code complet pour mon
RecyclerView.ItemDecoration
appeléHeaderItemDecoration
. Ensuite, j'explique les étapes suivies en détail.Logique métier
Alors, comment puis-je le faire tenir?
Vous ne le faites pas. Vous ne pouvez pas créer un
RecyclerView
élément de votre choix, arrêtez-vous et restez au top, à moins que vous ne soyez un gourou des mises en page personnalisées et que vous connaissiez plus de 12 000 lignes de codeRecyclerView
par cœur. Donc, comme cela va toujours avec la conception de l'interface utilisateur, si vous ne pouvez pas faire quelque chose, faites semblant. Vous venez de dessiner l'en-tête au-dessus de tout ce que vous utilisezCanvas
. Vous devez également savoir quels éléments l'utilisateur peut voir pour le moment. Cela se produit simplement, celaItemDecoration
peut vous fournir à la fois desCanvas
informations sur les éléments visibles. Avec cela, voici les étapes de base:Dans la
onDrawOver
méthode d'RecyclerView.ItemDecoration
obtention du tout premier élément (supérieur) visible par l'utilisateur.Déterminez quel en-tête le représente.
Dessinez l'en-tête approprié au-dessus de RecyclerView à l'aide de la
drawHeader()
méthode.Je souhaite également implémenter le comportement lorsque le nouvel en-tête à venir rencontre celui du haut: il devrait sembler que l'en-tête à venir pousse doucement l'en-tête actuel supérieur hors de la vue et prend finalement sa place.
La même technique de «dessiner par-dessus tout» s'applique ici.
Déterminez le moment où l'en-tête «bloqué» supérieur rencontre le nouveau à venir.
Obtenez ce point de contact (qui est le bas de l'en-tête collant de votre dessin et le haut de l'en-tête à venir).
Si l'élément de la liste empiète sur ce "point de contact", redessinez votre en-tête collant de sorte que son bas soit en haut de l'élément d'intrusion. Vous y parvenez avec la
translate()
méthode duCanvas
. En conséquence, le point de départ de l'en-tête supérieur sera hors de la zone visible, et il semblera "être poussé par l'en-tête à venir". Quand il est complètement parti, dessinez le nouvel en-tête en haut.Le reste est expliqué par des commentaires et des annotations approfondies dans le morceau de code que j'ai fourni.
L'utilisation est simple:
Vous
mAdapter
devez mettre en œuvreStickyHeaderInterface
pour que cela fonctionne. La mise en œuvre dépend des données dont vous disposez.Enfin, je fournis ici un gif avec des en-têtes semi-transparents, afin que vous puissiez saisir l'idée et voir réellement ce qui se passe sous le capot.
Voici l'illustration du concept «dessiner au-dessus de tout». Vous pouvez voir qu'il y a deux éléments "en-tête 1" - l'un que nous dessinons et reste en haut dans une position bloquée, et l'autre qui provient de l'ensemble de données et se déplace avec tous les autres éléments. L'utilisateur ne verra pas le fonctionnement interne de celui-ci, car vous n'aurez pas d'en-têtes semi-transparents.
Et voici ce qui se passe lors de la phase "expulsion":
J'espère que cela a aidé.
Éditer
Voici mon implémentation réelle de la
getHeaderPositionForItem()
méthode dans l'adaptateur de RecyclerView:Implémentation légèrement différente dans Kotlin
la source
private View getHeaderViewForItem(int itemPosition, RecyclerView parent) { int headerPosition = mListener.getHeaderPositionForItem(itemPosition); if(headerPosition != mCurrentHeaderIndex) { mCurrentHeader = mListener.createHeaderView(headerPosition, parent); mCurrentHeaderIndex = headerPosition; } return mCurrentHeader; }
Le moyen le plus simple consiste simplement à créer une décoration d'article pour votre RecyclerView.
}
XML pour votre en-tête dans recycler_section_header.xml:
Et enfin pour ajouter la décoration d'article à votre RecyclerView:
Avec cette décoration d'article, vous pouvez soit rendre l'en-tête épinglé / collé ou non avec juste un booléen lors de la création de la décoration d'article.
Vous pouvez trouver un exemple de travail complet sur github: https://github.com/paetztm/recycler_view_headers
la source
wrap_content
), vous voudrez également exécuterfixLayoutSize
après avoir défini le texte du titre.J'ai fait ma propre variante de la solution de Sébastyan ci-dessus
... et voici l'implémentation de StickyHeaderInterface (je l'ai fait directement dans l'adaptateur recycleur):
Ainsi, dans ce cas, l'en-tête ne consiste pas seulement à dessiner sur un canevas, mais à afficher avec un sélecteur ou une ondulation, un écouteur de clics, etc.
la source
recyclerView.addItemDecoration(HeaderItemDecoration(recyclerView, adapter))
. Désolé, je ne trouve pas d'exemple d'implémentation que j'ai utilisé. J'ai modifié la réponse - ajouté du texte aux commentairesà tous ceux qui recherchent une solution au problème de scintillement / clignotement lorsque vous en avez déjà
DividerItemDecoration
. il semble que je l'ai résolu comme ceci:cela semble fonctionner mais quelqu'un peut-il confirmer que je n'ai rien cassé d'autre?
la source
Vous pouvez vérifier et prendre l'implémentation de la classe
StickyHeaderHelper
dans mon projet FlexibleAdapter et l'adapter à votre cas d'utilisation.Mais, je suggère d'utiliser la bibliothèque car elle simplifie et réorganise la façon dont vous implémentez habituellement les adaptateurs pour RecyclerView: ne réinventez pas la roue.
Je dirais aussi, n'utilisez pas de décorateurs ou de bibliothèques obsolètes, et n'utilisez pas de bibliothèques qui ne font que 1 ou 3 choses, vous devrez fusionner vous-même les implémentations d'autres bibliothèques.
la source
Decorator
s?Une autre solution, basée sur l'écouteur scroll. Les conditions initiales sont les mêmes que dans la réponse de Sébastyan
Disposition pour ViewHolder et en-tête collant.
item_header.xml
Disposition pour RecyclerView
Classe pour HeaderItem.
Tout est utile. L'implémentation de l'adaptateur, ViewHolder et autres, n'est pas intéressante pour nous.
Interface pour la vue d'en-tête de liaison.
la source
for (int i = position; position >= 0; i--){ //should be i >= 0
Yo,
Voici comment procéder si vous ne voulez qu'un seul type de bâton de support lorsqu'il commence à sortir de l'écran (nous ne nous soucions d'aucune section). Il n'y a qu'une seule façon de ne pas casser la logique interne de RecyclerView des articles de recyclage et c'est de gonfler une vue supplémentaire au-dessus de l'élément d'en-tête de recyclerView et d'y passer des données. Je vais laisser parler le code.
Et puis vous faites cela dans votre adaptateur:
Où YOUR_STICKY_VIEW_HOLDER_TYPE est le type de vue de ce qui est censé être un support collant.
la source
Pour ceux qui peuvent être concernés. Sur la base de la réponse de Sébastyan, si vous voulez le faire défiler horizontalement. Tout simplement changer
getBottom()
engetRight()
etgetTop()
engetLeft()
la source
La réponse est déjà là. Si vous ne souhaitez utiliser aucune bibliothèque, vous pouvez suivre ces étapes:
Explication:
Dans la
onCreateViewHolder
méthode, nous pouvons vérifierviewType
et en fonction de la valeur (notre type "spécial") gonfler une mise en page spéciale.Par exemple:
où
class ItemElement
etclass TitleElement
peut ressembler à l'ordinaireViewHolder
:Donc l'idée de tout cela est intéressante. Mais je suis intéressé si c'est efficace, car nous devons trier la liste des données. Et je pense que cela réduira la vitesse. Si vous en pensez, écrivez-moi :)
Et aussi la question ouverte: comment tenir la mise en page "spéciale" sur le dessus, pendant que les articles sont recyclés. Peut-être combiner tout cela avec
CoordinatorLayout
.la source