J'ai un UITableView
avec un personnalisé UITableViewCell
défini dans un storyboard en utilisant la mise en page automatique. La cellule a plusieurs multilignes UILabels
.
Le UITableView
semble calculer correctement la hauteur des cellules, mais pour les premières cellules, cette hauteur n'est pas correctement répartie entre les étiquettes. Après avoir fait défiler un peu, tout fonctionne comme prévu (même les cellules initialement incorrectes).
- (void)viewDidLoad {
[super viewDidLoad]
// ...
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
// ...
// Set label.text for variable length string.
return cell;
}
Y a-t-il quelque chose qui me manque, qui empêche la mise en page automatique de faire son travail les premières fois?
J'ai créé un exemple de projet qui illustre ce comportement.
Réponses:
Je ne sais pas que cela est clairement documenté ou non, mais ajouter
[cell layoutIfNeeded]
avant de retourner la cellule résout votre problème.la source
-layoutIfNeeded
dans la cellule-awakeFromNib
. Je préfère n'appeler quelayoutIfNeeded
là où je sais pourquoi c'est nécessaire.Cela a fonctionné pour moi lorsque d'autres solutions similaires n'ont pas fonctionné:
Cela semble être un bogue réel car je suis très familier avec AutoLayout et comment utiliser UITableViewAutomaticDimension, mais je rencontre encore occasionnellement ce problème. Je suis content d'avoir enfin trouvé quelque chose qui fonctionne comme une solution de contournement.
la source
super.didMoveToSuperview()
didMoveToSuperview
: "L'implémentation par défaut de cette méthode ne fait rien."Ajout
[cell layoutIfNeeded]
danscellForRowAtIndexPath
ne fonctionne pas pour les cellules qui sont d' abord hors de défilaient vue.Ni le préfacer avec
[cell setNeedsLayout]
.Vous devez toujours faire défiler certaines cellules et les remettre en vue pour qu'elles se redimensionnent correctement.
C'est assez frustrant car la plupart des développeurs ont des cellules de type dynamique, de mise en page automatique et d'auto-dimensionnement fonctionnant correctement - à l'exception de ce cas ennuyeux. Ce bogue affecte tous mes contrôleurs de vue de table "plus hauts".
la source
[cell layoutSubviews]
au lieu de layoutIfNeeded pourrait être une solution possible. Reportez-vous à stackoverflow.com/a/33515872/1474113J'ai eu la même expérience dans l'un de mes projets.
Pourquoi ça arrive?
Cellule conçue dans Storyboard avec une certaine largeur pour certains appareils. Par exemple 400px. Par exemple, votre étiquette a la même largeur. Lorsqu'il se charge à partir du storyboard, il a une largeur de 400px.
Voici un problème:
tableView:heightForRowAtIndexPath:
appelé avant la mise en page de la cellule, ses sous-vues.Il a donc calculé la hauteur de l'étiquette et de la cellule d'une largeur de 400 px. Mais vous exécutez sur un appareil avec écran, par exemple, 320px. Et cette hauteur calculée automatiquement est incorrecte. Juste parce que les cellules ne
layoutSubviews
se produisent qu'aprèstableView:heightForRowAtIndexPath:
Même si vous définissezpreferredMaxLayoutWidth
manuellement votre étiquette,layoutSubviews
cela n'aide pas.Ma solution:
1) Sous
UITableView
- classe et remplacementdequeueReusableCellWithIdentifier:forIndexPath:
. Définissez la largeur de cellule égale à la largeur du tableau et forcez la disposition de la cellule.2) Sous-classe
UITableViewCell
. DéfinissezpreferredMaxLayoutWidth
manuellement vos étiquettes danslayoutSubviews
. Vous avez également besoin d'une mise en page manuellecontentView
, car elle n'est pas mise en page automatiquement après le changement de cadre de cellule (je ne sais pas pourquoi, mais c'est le cas)la source
cell.frame.size.width = tableview.frame.width
puiscell.layoutIfNeeded()
dans lacellForRowAt
fonction a fait l'affaire pour moiJ'ai un problème similaire, au premier chargement, la hauteur de ligne n'a pas été calculée mais après quelques défilement ou aller sur un autre écran et je reviens à cet écran, les lignes sont calculées. Au premier chargement, mes articles sont chargés à partir d'Internet et au deuxième chargement, mes articles sont d'abord chargés à partir de Core Data et rechargés à partir d'Internet et j'ai remarqué que la hauteur des lignes est calculée au rechargement d'Internet. J'ai donc remarqué que lorsque tableView.reloadData () est appelé pendant l'animation de segue (même problème avec push et present segue), la hauteur de ligne n'était pas calculée. J'ai donc caché la tableview lors de l'initialisation de la vue et mis un chargeur d'activité pour éviter un effet laid à l'utilisateur et j'appelle tableView.reloadData après 300 ms et maintenant le problème est résolu. Je pense que c'est un bogue UIKit mais cette solution de contournement fait l'affaire.
J'ai mis ces lignes (Swift 3.0) dans mon gestionnaire d'achèvement de chargement d'éléments
Cela explique pourquoi pour certaines personnes, mettez un reloadData dans layoutSubviews résolvent le problème
la source
aucune des solutions ci-dessus n'a fonctionné pour moi, ce qui a fonctionné est cette recette de magie: appelez-les dans cet ordre:
tableView.reloadData()
tableView.layoutIfNeeded() tableView.beginUpdates() tableView.endUpdates()
mes données tableView sont remplies à partir d'un service Web, dans le rappel de la connexion, j'écris les lignes ci-dessus.
la source
Dans mon cas, la dernière ligne du UILabel était tronquée lorsque la cellule était affichée pour la première fois. Cela s'est produit de manière assez aléatoire et la seule façon de la dimensionner correctement était de faire défiler la cellule hors de la vue et de la ramener. J'ai essayé toutes les solutions possibles affichées jusqu'à présent (layoutIfNeeded..reloadData) mais rien n'a fonctionné pour moi. L'astuce consistait à régler "Autoshrink" sur Minimuum Font Scale (0,5 pour moi). Essaie
la source
Ajoutez une contrainte pour tout le contenu dans une cellule personnalisée de vue de tableau, puis estimez la hauteur de ligne de vue de tableau et définissez la hauteur de ligne sur une dimension automatique avec un chargement viewdid:
Pour résoudre ce problème de chargement initial, appliquez la méthode layoutIfNeeded avec dans une cellule de vue de tableau personnalisée:
la source
estimatedRowHeight
une valeur> 0 et non àUITableViewAutomaticDimension
(qui est -1), sinon la hauteur de ligne automatique ne fonctionnera pas.J'ai essayé la plupart des réponses à cette question et je n'ai pu en faire fonctionner aucune. La seule solution fonctionnelle que j'ai trouvée était d'ajouter ce qui suit à ma
UITableViewController
sous - classe:L'
UIView.performWithoutAnimation
appel est requis, sinon vous verrez l'animation de vue de table normale pendant le chargement du contrôleur de vue.la source
viewWillAppear
n'a pas fonctionné pour moi, mais le faireviewDidAppear
a fonctionné.Le réglage
preferredMaxLayoutWidth
aide dans mon cas. J'ai ajoutédans mon code.
Référez-vous également à Le texte sur une seule ligne prend deux lignes dans UILabel et http://openradar.appspot.com/17799811 .
la source
appeler
cell.layoutIfNeeded()
à l' intérieur acellForRowAt
fonctionné pour moi sur ios 10 et ios 11, mais pas sur ios 9.pour obtenir ce travail sur ios 9 également, j'appelle
cell.layoutSubviews()
et il a fait l'affaire.la source
Pour moi, aucune de ces approches n'a fonctionné, mais j'ai découvert que l'étiquette avait un
Preferred Width
ensemble explicite dans Interface Builder. Supprimer cela (décocher "Explicite") puis utiliser aUITableViewAutomaticDimension
fonctionné comme prévu.la source
J'ai essayé toutes les solutions de cette page, mais décocher utiliser les classes de taille, puis la vérifier à nouveau a résolu mon problème.
Edit: décocher les classes de taille cause beaucoup de problèmes sur le storyboard, j'ai donc essayé une autre solution. Je peuplaient mon avis de la table à mon avis de contrôleur
viewDidLoad
etviewWillAppear
méthodes. Cela a résolu mon problème.la source
J'ai un problème avec le redimensionnement de l'étiquette, donc je n'ai
besoin que de faire chatTextLabel.text = chatMessage.message chatTextLabel? .UpdateConstraints () après avoir configuré le texte
// code complet
la source
Dans mon cas, je mettais à jour dans un autre cycle. La hauteur de tableViewCell a donc été mise à jour après la définition de labelText. J'ai supprimé le bloc asynchrone.
la source
Assurez-vous simplement de ne pas définir le texte de l'étiquette dans la méthode déléguée «willdisplaycell» de la vue tableau. Définissez le texte de l'étiquette dans la méthode déléguée 'cellForRowAtindexPath' pour le calcul dynamique de la hauteur.
De rien :)
la source
Dans mon cas, une vue de pile dans la cellule causait le problème. C'est un bug apparemment. Une fois que je l'ai supprimé, le problème a été résolu.
la source
Le problème est que les cellules initiales se chargent avant d'avoir une hauteur de ligne valide. La solution de contournement consiste à forcer un rechargement de table lorsque la vue apparaît.
la source
Pour iOS 12+ uniquement, à partir de 2019 ...
Un exemple continu d'incompétence bizarre occasionnelle d'Apple, où les problèmes durent littéralement des années.
Il semble que ce soit le cas
va le réparer. (Vous perdez des performances bien sûr.)
Telle est la vie avec Apple.
la source
Dans mon cas, le problème avec la hauteur de la cellule se produit après le chargement de la vue de table initiale et une action de l'utilisateur a lieu (en appuyant sur un bouton dans une cellule qui a pour effet de modifier la hauteur de la cellule). J'ai été incapable de faire changer la hauteur de la cellule à moins que je ne le fasse:
J'ai essayé
mais cela n'a pas fonctionné.
la source
Dans Swift 3. J'ai dû appeler self.layoutIfNeeded () chaque fois que je mettais à jour le texte de la cellule réutilisable.
la source
Aucune des solutions ci-dessus n'a fonctionné, mais la combinaison suivante des suggestions a fonctionné.
J'ai dû ajouter ce qui suit dans viewDidLoad ().
La combinaison ci-dessus de reloadData, setNeedsLayout et layoutIfNeeded a fonctionné mais aucune autre. Cela pourrait être spécifique aux cellules du projet. Et oui, j'ai dû invoquer reloadData deux fois pour le faire fonctionner.
Définissez également les éléments suivants dans viewDidLoad
Dans tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
la source
reloadData/beginUpdates/endUpdates/reloadData
fonctionne également;reloadData
doit être appelé une seconde fois. Pas besoin de l'envelopperasync
.J'ai rencontré ce problème et je l'ai résolu en déplaçant mon code d'initialisation de vue / étiquette de
tableView(willDisplay cell:)
ÀtableView(cellForRowAt:)
.la source
willDisplay
aura de meilleures performances quecellForRowAt
. Utilisez le dernier uniquement pour instancier la bonne cellule.willDisplay
avez de meilleures performances, il est recommandé d'initialiser l'interface utilisateur de votre cellulecellForRowAt
lorsque la mise en page est automatique. En effet, la mise en page est calculée par UIKit après cellForRowAt et avant willDisplay. Donc, si la hauteur de votre cellule dépend de son contenu, initialisez le contenu de l'étiquette (ou autre) danscellForRowAt
.utilisez la méthode ci-dessus qui renvoie dynamiquement la hauteur de la ligne. Et attribuez la même hauteur dynamique à l'étiquette que vous utilisez.
Ce code vous aide à trouver la hauteur dynamique du texte affiché dans l'étiquette.
la source