UICollectionView à l'intérieur d'un UITableViewCell — dynamique de la hauteur?
L'un de nos écrans de l'application nous demande de placer un UICollectionView
à l'intérieur d'un UITableViewCell
. Cette UICollectionView
aura une dynamique nombre d'éléments, résultant en une hauteur qui doit être calculé de façon dynamique ainsi. Cependant, je suis en cours d'exécution à des problèmes en essayant de calculer la hauteur de l'embedded UICollectionView
.
Notre premier UIViewController
a été créé dans les Storyboards et ne faire usage de la mise en page automatique. Mais, je ne sais pas comment faire pour augmenter dynamiquement la hauteur de la UITableViewCell
basé sur la hauteur de la UICollectionView
.
Quelqu'un peut-il donner quelques conseils ou des conseils sur la façon d'accomplir cette?
- pouvez-vous en dire un peu plus sur la mise en page que vous essayez d'accomplir ? Est la hauteur de la
UITableViewCell
différent de son acutal tableview ? Avez-vous besoin d'un défilement vertical sur leUICollectionView
et laUITableView
- La hauteur de la UITableViewCell est censé être dynamique, basé sur la hauteur de la UICollectionView qui fait partie de l'affichage de la table de la cellule. La mise en page de mon UICollectionView est de 4 colonnes et un nombre dynamique de lignes. Ainsi, avec 100 points, j'aurais 4 colonnes et 25 lignes de mon UICollectionView. La hauteur de la cellule particulière -- comme indiqué par UITableView de heightForRowAtIndexPath -- doit être en mesure d'ajuster en fonction de la taille de cet UICollectionView. Est un peu plus clair?
- merci de me suggérer une solution à cette situation
Vous devez vous connecter pour publier un commentaire.
La bonne réponse est OUI, vous PEUT ce faire.
Je suis tombé sur ce problème il y a quelques semaines. Il est effectivement plus facile que vous pouvez penser. Mettez vos cellules en Plumes (ou story-boards) et la broche, je les mise en page automatique faire tout le travail
Compte tenu de la structure suivante:
La solution est-à-dire mise en page automatique pour calculer d'abord le collectionViewCell tailles, puis l'affichage de la collection contentSize, et l'utiliser comme la taille de votre cellule. C'est le UIView méthode que "la magie":
Vous devez définir ici la taille de la TableViewCell, qui dans votre cas est le CollectionView de contentSize.
CollectionViewCell
À la CollectionViewCell que vous avez à dire à la cellule de mise en page à chaque fois que vous changer de modèle (par ex.: vous définissez un UILabel avec un texte, puis la cellule doit être mise de nouveau).
TableViewCell
La TableViewCell fait la magie. Il dispose d'une prise pour votre collectionView, permet la mise en page automatique pour collectionView cellules à l'aide de estimatedItemSize de la UICollectionViewFlowLayout.
Alors, le truc, c'est à définir votre tableView de la cellule la taille à la systemLayoutSizeFittingSize... méthode. (NOTE: iOS8 ou plus tard)
NOTE: j'ai essayé d'utiliser le délégué de la cellule de la hauteur de la méthode de la tableView
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
.mais il est trop tard pour la mise en page automatique du système pour calculer la CollectionView contentSize et parfois vous pouvez trouver mal redimensionnée cellules.TableViewController
Oubliez pas d'activer la mise en page automatique du système pour la tableView cellules à votre TableViewController:
De CRÉDIT: @rbarbera aidé à démêler
cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);
Cela permettra de "simuler" une longue cellule avec une longue collectionView, de sorte que le collectionView permettra de calculer la taille de l'ensemble de ses cellules. Sinon, le collectionView calculée visibles seulement la taille de la cellule, et de définir, à tort, la talbeViewCell hauteur.estimatedSize
de ne pas faire l'affairecollectionViewHeightConstraint.constant = collectionView.collectionViewLayout.collectionViewContentSize().height
puisreturn self.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
cell.bounds
truc, c'est la partie la plus importante. Je suis l'aide d'une tableView à l'intérieur d'une tableView cellule (presque la même configuration) et sans réglage de la table externecell.bounds
d'une énorme hauteur, il n'a pas de calculer lacontentSize
correctement.tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
. Je suis au début de lacell.bounds
, l'intégralité de la cellule de mise en page sera configurésystemLayoutSizeFittingSize
, j'ai frappé un problème dans swift lors du rechargement de la cellule, apps semble coincé après laself.collectionView.layoutIfNeeded()
. Je l'ai fixée par le réglage de la hauteur du châssis avec 1 plutôt que la hauteur maximale. Espérons que son aide si quelqu'un pèche contre ce problème.systemLayoutSizeFittingSize
droite avant d'appelerlayoutIfNeeded
sur le collectionview, je peux voir queself.bounds
(les limites de la tableview cellule) a une largeur de 363 pixels. Mais après l'appel delayoutIfNeeded
sur le collectionview, la taille de la collectionview (contentSize, ou le cadre) a une plus grande largeur (606 pixels), même si elle est épinglé avec des contraintes à l'intérieur de la tableview cellule. Ainsi, la première foissystemLayoutSizeFittingSize
renvoie une valeur, la valeur est erronée.systemLayoutSizeFitting
, d'inverser l'ordre de ce qui est indiqué dans la réponse, de sorte que la premièrecollectionView.layoutIfNeeded()
s'exécute, puiscollectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
Je pense, mon chemin est beaucoup plus simple, a alors proposé par @PabloRomeu.
L'étape 1. Créer de la prise de
UICollectionView
àUITableViewCell subclass
, oùUICollectionView
est placé. Laissez, c'est le nom seracollectionView
L'étape 2. Ajouter de l'IB pour
UICollectionView
hauteur de la contrainte et de créer de la prise deUITableViewCell subclass
trop. Laissez, c'est le nom seracollectionViewHeight
.L'étape 3. Dans
tableView:cellForRowAtIndexPath:
code d'ajout:collectionView
de tous les côtés deUITableViewCell
et définirtableView.estimatedRowHeight = 44;
ettableView.rowHeight = UITableViewAutomaticDimension;
[cell layoutIfNeeded]; [cell.collectionView reloadData];
Les deux vues de table et les vues de la collection
UIScrollView
sous-classes, et donc n'aime pas être imbriquées à l'intérieur un autre de défilement de la vue, comme ils essaient de calculer le contenu de tailles, de la réutilisation des cellules, etc.Je vous recommande de n'utiliser qu'une vue de collection pour tous vos fins.
Vous pouvez le diviser en sections et "traiter" certaines sections " mise en page comme une vue de table et d'autres en vue d'une collection. Après tout, il n'y a rien que vous ne pouvez pas atteindre avec une vue de collection que vous pouvez avec une vue de la table.
Si vous avez une base de la grille de mise en page pour votre vue de collection "pièces", vous pouvez aussi utiliser les cellules d'un tableau pour les gérer. Si vous n'avez pas besoin de iOS 5 il est mieux d'utiliser les vues de la collection.
layoutAttributesForItemAtIndexPath
pour les différentes sections de mon propre sous-classe deUICollectionViewLayout
?Pablo Romeu réponse ci-dessus (https://stackoverflow.com/a/33364092/2704206) m'a aidé énormément avec mon problème. J'ai dû faire quelques petites choses différemment, cependant, pour obtenir ce travail à mon problème. Tout d'abord, je n'ai pas eu à appeler
layoutIfNeeded()
comme souvent. Je n'avais qu'à l'appeler sur lecollectionView
dans lesystemLayoutSizeFitting
fonction.Deuxièmement, j'ai eu l'auto contraintes de mise en forme sur ma collection afficher dans la vue de table de la cellule pour lui donner une certaine marge. J'ai donc dû soustraire à l'attaque et de fuite des marges de la
targetSize.width
lors de la configuration de lacollectionView.frame
's largeur. J'ai également eu à ajouter les marges supérieure et inférieure à la valeur de retourCGSize
hauteur.Pour obtenir ces contraintes constantes, j'ai eu la possibilité de créer des points de vente pour les contraintes, de codage en dur leurs constantes, ou en consultant par un identificateur. J'ai décidé d'aller avec la troisième option pour faire mon tableau personnalisé de vue de la cellule classe facilement réutilisables. En fin de compte, c'était tout ce dont j'avais besoin pour le faire fonctionner:
Comme une fonction d'aide pour récupérer une contrainte en identifiant, j'ai ajouter l'extension suivante:
REMARQUE: Vous devez définir l'identificateur de ces contraintes dans votre storyboard, ou partout où ils sont en cours de création. À moins d'avoir un 0 constante, alors il n'a pas d'importance. Aussi, comme dans Pablo réponse, vous aurez besoin d'utiliser
UICollectionViewFlowLayout
que la mise en page de votre collection de point de vue. Enfin, assurez-vous de relier lecollectionView
IBOutlet à votre storyboard.Avec la vue du tableau de la cellule ci-dessus, je peux maintenant sous-classe d'une autre vue de la table de cellules qui ont besoin d'une vue de collection et ont à mettre en œuvre le
UICollectionViewDelegateFlowLayout
etUICollectionViewDataSource
protocoles. Espérons que cela est utile à quelqu'un d'autre!Je mettrais une méthode statique sur l'affichage de la collection de la classe qui sera de retour une taille basée sur le contenu qu'il aura. Ensuite, utilisez la méthode dans la
heightForRowAtIndexPath
pour revenir à la bonne taille.Notez également que vous pouvez obtenir certains comportement bizarre lorsque vous incorporez ces sortes de viewControllers. Je l'ai fait une fois et avait d'étranges problèmes de mémoire je n'ai jamais travaillé.
Peut-être que ma variante sera utile; j'ai décider de cette tâche au cours des deux dernières heures. Je ne prétends pas que c'est 100% correct ou optimale, mais mes compétences sont de très petits encore, et j'aimerais entendre les commentaires de spécialistes. Je vous remercie.
Une remarque importante: cette méthode fonctionne pour la statique de la table - il est spécifié par mon travail actuel.
Donc, tout ce que j'utilise est viewWillLayoutSubviews de tableView. Et un peu plus.
Une alternative à Pablo Romeu solution est de personnaliser UICollectionView lui-même, plutôt que de faire le travail dans la vue tableau de cellules.
Le problème sous-jacent est que, par défaut, la vue d'une collection n'a pas de taille intrinsèque et donc ne peut pas informer disposition automatique des dimensions à utiliser. Vous pouvez remédier à cela en créant une sous-classe personnalisée qui retourne une utilité intrinsèque de la taille.
Créer une sous-classe de UICollectionView et remplacer les méthodes suivantes
(Vous devriez également de remplacer les méthodes associées: reloadSections, reloadItemsAtIndexPaths d'une manière similaire à reloadData())
Appel layoutIfNeeded les forces de l'affichage de la collection de recalculer la taille du contenu, qui peut ensuite être utilisé comme la nouvelle taille intrinsèque.
Aussi, vous devez explicitement gérer les modifications apportées à la taille de la vue (par exemple, sur le dispositif de rotation) dans le table view controller
Approche la plus facile que j'ai est venu avec, jusqu'à présent, les Crédits à @igor réponse ci-dessus,
Dans votre tableviewcell classe il suffit d'insérer ce
et, bien sûr, changer la collectionviewoutlet avec votre prise de courant dans la cellule de la classe
J'ai lu toutes les réponses. Cela semble servir tous les cas.
Pablo solution ne fonctionne pas très bien pour moi, j'ai eu d'étranges effets visuels (le collectionView ne pas ajuster correctement).
Ce qui a fonctionné a été pour ajuster la hauteur de la contrainte de la collectionView (comme un NSLayoutConstraint) à la collectionView contentSize pendant
layoutSubviews()
. C'est la méthode appelée lors de la mise en page automatique est appliqué à la cellule.J'ai été confrontée au même problème récemment et j'ai presque tout essayé solution dans les réponses, certains d'entre eux ont travaillé et ce n'était pas ma principale préoccupation à propos de @PabloRomeu approche est que si vous avez d'autres contenus dans la cellule (autres que l'affichage de la collection), vous aurez pour calculer leur taille et la hauteur de leurs contraintes et de retourner le résultat à obtenir la mise en page automatique de droite et je n'aime pas à calculer les choses manuellement dans mon code. Voici donc la solution qui a bien fonctionné pour moi, sans faire des calculs manuels dans mon code.
dans le
cellForRow:atIndexPath
de la vue de la table je ne les suivants:Je pense que ce qui se passe ici, c'est que je force la tableview cellule d'ajuster sa hauteur après l'affichage de la collection de la hauteur a été calculée. (après la fourniture de la collectionView date de la source de données)
- Je obtenir de l'idée de @Igor post et d'investir mon temps pour mon projet avec swift
Juste passé dans votre
Plus:
Si vous voyez votre UICollectionView saccadée lors du chargement de cellules.
Dans votre UITableViewDelegate:
Substitut itemCount et CollectionViewCellHeight avec les valeurs réelles. Si vous avez un tableau de tableaux itemCount pourrait être:
Ou quoi que ce soit.
collectionViewCellHeight
avant qu'il affiche.1.Créer dummy cellule.
2.Utilisation collectionViewContentSize méthode sur UICollectionViewLayout de UICollectionView à l'aide des données actuelles.
Vous pouvez calculer la hauteur de la collection en fonction de ses propriétés comme
itemSize
,sectionInset
,minimumLineSpacing
,minimumInteritemSpacing
, si votre collectionViewCell a la frontière de la règle.