J'utilise un UICollectionView dans mon projet, où il y a plusieurs cellules de largeurs différentes sur une ligne. Selon: https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/UsingtheFlowLayout/UsingtheFlowLayout.html
il répartit les cellules sur la ligne avec un remplissage égal. Cela se produit comme prévu, sauf que je veux les justifier à gauche et coder en dur une largeur de remplissage.
Je pense que je dois sous-classer UICollectionViewFlowLayout, mais après avoir lu certains des didacticiels, etc. en ligne, je ne semble tout simplement pas comprendre comment cela fonctionne.
Réponses:
Les autres solutions de ce fil ne fonctionnent pas correctement, lorsque la ligne est composée d'un seul élément ou sont trop compliquées.
Sur la base de l'exemple donné par Ryan, j'ai changé le code pour détecter une nouvelle ligne en inspectant la position Y du nouvel élément. Très simple et rapide en performance.
Rapide:
Si vous souhaitez que les vues supplémentaires conservent leur taille, ajoutez ce qui suit en haut de la clôture de l'
forEach
appel:Objectif c:
la source
let attributes = super.layoutAttributesForElementsInRect(rect)?.map { $0.copy() as! UICollectionViewLayoutAttributes }
Les réponses à cette question contiennent de nombreuses idées intéressantes. Cependant, la plupart d'entre eux présentent certains inconvénients:
La plupart des solutions remplacent uniquement la
layoutAttributesForElements(in rect: CGRect)
fonction. Ils ne prévalent paslayoutAttributesForItem(at indexPath: IndexPath)
. Ceci est un problème car la vue de collection appelle périodiquement la dernière fonction pour récupérer les attributs de mise en page pour un chemin d'index particulier. Si vous ne renvoyez pas les attributs appropriés de cette fonction, vous risquez de rencontrer toutes sortes de bogues visuels, par exemple lors des animations d'insertion et de suppression de cellules ou lors de l'utilisation de cellules auto-dimensionnées en définissant la disposition de la vue de collectionestimatedItemSize
. L' état des documents Apple :De nombreuses solutions émettent également des hypothèses sur le
rect
paramètre passé à lalayoutAttributesForElements(in rect: CGRect)
fonction. Par exemple, beaucoup sont basés sur l'hypothèse que lerect
commence toujours au début d'une nouvelle ligne, ce qui n'est pas nécessairement le cas.Donc en d'autres termes:
La plupart des solutions suggérées sur cette page fonctionnent pour certaines applications spécifiques, mais elles ne fonctionnent pas comme prévu dans toutes les situations.
AlignedCollectionViewFlowLayout
Afin de résoudre ces problèmes, j'ai créé une
UICollectionViewFlowLayout
sous-classe qui suit une idée similaire à celle suggérée par Matt et Chris Wagner dans leurs réponses à une question similaire. Il peut soit aligner les cellules⬅︎ à gauche :
ou à ➡︎ droite :
et offre en outre des options pour aligner verticalement les cellules dans leurs rangées respectives (au cas où elles varient en hauteur).
Vous pouvez simplement le télécharger ici:
https://github.com/mischa-hildebrand/AlignedCollectionViewFlowLayout
L'utilisation est simple et expliquée dans le fichier README. En gros, vous créez une instance de
AlignedCollectionViewFlowLayout
, spécifiez l'alignement souhaité et attribuez-le à lacollectionViewLayout
propriété de votre vue de collection :(Il est également disponible sur Cocoapods .)
Comment ça marche (pour les cellules alignées à gauche):
Le concept ici est de s'appuyer uniquement sur la
layoutAttributesForItem(at indexPath: IndexPath)
fonction . Dans le,layoutAttributesForElements(in rect: CGRect)
nous obtenons simplement les chemins d'index de toutes les cellules dans lerect
, puis appelons la première fonction pour chaque chemin d'index pour récupérer les images correctes:(La
copy()
fonction crée simplement une copie complète de tous les attributs de disposition du tableau. Vous pouvez consulter le code source pour son implémentation.)Alors maintenant, la seule chose que nous avons à faire est d'implémenter
layoutAttributesForItem(at indexPath: IndexPath)
correctement la fonction. La super classeUICollectionViewFlowLayout
place déjà le nombre correct de cellules dans chaque ligne, nous n'avons donc qu'à les déplacer vers la gauche dans leur ligne respective. La difficulté réside dans le calcul de la quantité d'espace dont nous avons besoin pour déplacer chaque cellule vers la gauche.Comme nous voulons avoir un espacement fixe entre les cellules, l'idée de base est simplement de supposer que la cellule précédente (la cellule à gauche de la cellule actuellement disposée) est déjà positionnée correctement. Ensuite, il suffit d'ajouter l'espacement des cellules à la
maxX
valeur du cadre de la cellule précédente et c'est laorigin.x
valeur du cadre de la cellule actuelle.Maintenant, nous avons seulement besoin de savoir quand nous avons atteint le début d'une ligne, afin de ne pas aligner une cellule à côté d'une cellule de la ligne précédente. (Cela entraînerait non seulement une mise en page incorrecte, mais ce serait également extrêmement lent.) Nous devons donc avoir une ancre de récursivité. L'approche que j'utilise pour trouver cette ancre de récursivité est la suivante:
Pour savoir si la cellule d'index i est dans la même ligne que la cellule d'index i-1 ...
... Je "dessine" un rectangle autour de la cellule courante et je l'étire sur toute la largeur de la vue de la collection. Comme les
UICollectionViewFlowLayout
centres toutes les cellules verticalement, chaque cellule de la même ligne doit croiser ce rectangle.Ainsi, je vérifie simplement si la cellule d'index i-1 croise ce rectangle de ligne créé à partir de la cellule d'index i .
Si elle se coupe, la cellule d'index i n'est pas la cellule la plus à gauche de la ligne.
→ Récupère l'image de la cellule précédente (avec l'index i − 1 ) et déplace la cellule courante à côté d'elle.
Si elle ne se coupe pas, la cellule d'index i est la cellule la plus à gauche de la ligne.
→ Déplacez la cellule vers le bord gauche de la vue de collection (sans changer sa position verticale).
Je ne publierai pas l'implémentation réelle de la
layoutAttributesForItem(at indexPath: IndexPath)
fonction ici car je pense que la partie la plus importante est de comprendre l' idée et vous pouvez toujours vérifier mon implémentation dans le code source . (C'est un peu plus compliqué qu'expliqué ici car j'autorise également l'.right
alignement et diverses options d'alignement vertical. Cependant, cela suit la même idée.)Wow, je suppose que c'est la réponse la plus longue que j'ai jamais écrite sur Stackoverflow. J'espère que ça aide. 😉
la source
Avec Swift 4.1 et iOS 11, selon vos besoins, vous pouvez choisir l'une des 2 implémentations complètes suivantes afin de résoudre votre problème.
#1. Alignement à gauche autoresizing
UICollectionViewCell
sLa mise en œuvre ci - dessous montre comment utiliser
UICollectionViewLayout
« slayoutAttributesForElements(in:)
,UICollectionViewFlowLayout
» sestimatedItemSize
etUILabel
« spreferredMaxLayoutWidth
pour les cellules gauche Autoresizing d'alignement dansUICollectionView
:CollectionViewController.swift
FlowLayout.swift
CollectionViewCell.swift
Résultat attendu:
# 2. Aligner à gauche
UICollectionViewCell
avec une taille fixeLa mise en œuvre ci-dessous montre comment utiliser
UICollectionViewLayout
leslayoutAttributesForElements(in:)
etUICollectionViewFlowLayout
lesitemSize
pour aligner à gauche les cellules avec une taille prédéfinie dans unUICollectionView
:CollectionViewController.swift
FlowLayout.swift
CollectionViewCell.swift
Résultat attendu:
la source
10
un nombre arbitraire est-elle?La solution simple en 2019
C'est l'une de ces questions déprimantes où les choses ont beaucoup changé au fil des ans. C'est maintenant facile.
En gros, vous faites simplement ceci:
Tout ce dont vous avez besoin maintenant est le code passe-partout:
Copiez et collez simplement cela dans un
UICollectionViewFlowLayout
- vous avez terminé.Solution de travail complète pour copier et coller:
C'est le tout:
Et enfin...
Remerciez @AlexShubin ci-dessus qui a clarifié cela pour la première fois!
la source
La question se pose depuis un certain temps, mais il n'y a pas de réponse et c'est une bonne question. La réponse est de remplacer une méthode dans la sous-classe UICollectionViewFlowLayout:
Comme recommandé par Apple, vous obtenez les attributs de mise en page de super et les itérez dessus. Si c'est le premier de la ligne (défini par son origine.x étant sur la marge de gauche), vous le laissez seul et remettez le x à zéro. Ensuite, pour la première cellule et chaque cellule, vous ajoutez la largeur de cette cellule plus une marge. Cela est passé à l'élément suivant de la boucle. S'il ne s'agit pas du premier élément, définissez son origine.x sur la marge calculée en cours d'exécution et ajoutez de nouveaux éléments au tableau.
la source
attribute.center.x == self.collectionView?.bounds.midX
leftMargin
avec laif (attributes.frame.origin.x == self.sectionInset.left) {
vérification. Cela suppose que la disposition par défaut a aligné la cellule de la nouvelle ligne pour qu'elle soit alignée avec lesectionInset.left
. Si ce n'est pas le cas, le comportement que vous décrivez en résultera. J'insérerais un point d'arrêt à l'intérieur de la boucle et vérifierais les deux côtés pour la cellule de la deuxième ligne juste avant la comparaison. Bonne chance.J'ai eu le même problème, essayez le Cocoapod UICollectionViewLeftAlignedLayout . Incluez-le simplement dans votre projet et initialisez-le comme ceci:
la source
En me basant sur la réponse de Michael Sand , j'ai créé une
UICollectionViewFlowLayout
bibliothèque sous- classée pour effectuer une justification horizontale à gauche, à droite ou complète (fondamentalement par défaut) - elle vous permet également de définir la distance absolue entre chaque cellule. Je prévois d'y ajouter une justification horizontale du centre et une justification verticale.https://github.com/eroth/ERJustifiedFlowLayout
la source
Voici la réponse originale dans Swift. Cela fonctionne toujours très bien.
Exception: redimensionnement automatique des cellules
Il y a malheureusement une grande exception. Si vous utilisez
UICollectionViewFlowLayout
des fichiersestimatedItemSize
. En interne,UICollectionViewFlowLayout
cela change un peu les choses. Je ne l'ai pas entièrement retracé, mais il est clair qu'il appelle d'autres méthodes après avoirlayoutAttributesForElementsInRect
auto-dimensionné les cellules. D'après mes essais et erreurs, j'ai constaté qu'il semble appelerlayoutAttributesForItemAtIndexPath
plus souvent chaque cellule individuellement lors du dimensionnement automatique. Cette mise à jourLeftAlignedFlowLayout
fonctionne très bien avecestimatedItemSize
. Cela fonctionne également avec des cellules de taille statique, mais les appels de mise en page supplémentaires m'amènent à utiliser la réponse d'origine chaque fois que je n'ai pas besoin de cellules de dimensionnement automatique.la source
En rapide. Selon la réponse de Michaels
la source
Sur la base de toutes les réponses, je change un peu et cela fonctionne bien pour moi
la source
Si l'un de vous est confronté à un problème, certaines des cellules qui se trouvent à droite de la vue de collection dépassent les limites de la vue de collection . Alors veuillez utiliser ceci -
Utilisez INT au lieu de comparer les valeurs CGFloat .
la source
Basé sur les réponses ici, mais correction des plantages et des problèmes d'alignement lorsque la vue de votre collection contient également des en-têtes ou des pieds de page. Aligner les cellules à gauche uniquement:
la source
Merci pour la réponse de Michael Sand . Je l'ai modifié en une solution de plusieurs lignes (le même alignement en haut y de chaque ligne) qui est alignement à gauche, même espacement pour chaque élément.
la source
Voici mon parcours pour trouver le meilleur code qui fonctionne avec Swift 5. J'ai joint quelques réponses de ce fil et d'autres fils pour résoudre les avertissements et les problèmes auxquels j'ai été confronté. J'ai eu un avertissement et un comportement anormal lors du défilement dans la vue de ma collection. La console imprime les éléments suivants:
Un autre problème auquel j'ai été confronté est que certaines cellules longues sont rognées sur le côté droit de l'écran. En outre, je définissais les insertions de section et le minimumInteritemSpacing dans les fonctions de délégué qui entraînaient des valeurs ne se reflétaient pas dans la classe personnalisée. Le correctif pour cela était de définir ces attributs sur une instance de la mise en page avant de l'appliquer à ma vue de collection.
Voici comment j'ai utilisé la mise en page pour ma vue de collection:
Voici la classe de disposition de flux
la source
Le problème avec UICollectionView est qu'il essaie d'ajuster automatiquement les cellules dans la zone disponible. J'ai fait cela en définissant d'abord le nombre de lignes et de colonnes, puis en définissant la taille de cellule pour cette ligne et cette colonne
1) Pour définir des sections (lignes) de mon UICollectionView:
2) Pour définir le nombre d'éléments dans une section. Vous pouvez définir un nombre différent d'articles pour chaque section. vous pouvez obtenir le numéro de section en utilisant le paramètre «section».
3) Pour définir la taille de cellule pour chaque section et ligne séparément. Vous pouvez obtenir le numéro de section et le numéro de ligne en utilisant le paramètre 'indexPath', c'est-
[indexPath section]
à- dire pour le numéro de section et[indexPath row]
pour le numéro de ligne.4) Ensuite, vous pouvez afficher vos cellules en lignes et en sections en utilisant:
REMARQUE: dans UICollectionView
la source
La réponse de Mike Sand est bonne mais j'avais rencontré des problèmes avec ce code (comme une longue cellule coupée). Et nouveau code:
la source
Modification de la réponse d'Angel García Olloqui au respect de la part
minimumInteritemSpacing
du déléguécollectionView(_:layout:minimumInteritemSpacingForSectionAt:)
, si elle la met en œuvre.la source
Le code ci-dessus fonctionne pour moi. Je souhaite partager le code Swift 3.0 respectif.
la source