J'ai une vue sous forme de tableau avec le potentiel pour chaque cellule d'avoir sa propre hauteur, donc ne convient pas pour utiliser rowHeight
. Au lieu de cela, j'utilise actuellement let indexSet = NSIndexSet(index: 10)
et self.tableView.estimatedRowHeight = 75
. Cela signifie qu'il appelle la fonction sizeThatFits
sur la cellule pour déterminer sa hauteur. Tout cela fonctionne bien.
Le problème est alors lorsque vous rechargez une cellule qui est à l'écran. Faites défiler la liste vers le bas pour afficher la cellule 10, par exemple, puis rechargez la cellule 10, fonctionne bien. Mais lorsque vous commencez à remonter dans le champ, après les cellules que vous avez déjà vues, la valeur de valeur estimée pour RowReight est ignorée pour chaque cellule, sans tenir compte de la variable sizeThatFits
. Il serait impossible pour moi de donner une estimation précise ou assez bonne de RowReight afin que ce saut ne soit pas perceptible, car mes cellules pourront afficher une ligne de texte ou une image complète, ce qui constitue une différence importante. Taille.
J'ai montré cet effet ici:
J'ai fait de nombreuses tentatives différentes en combinant hauteurForRowAtIndexPath, estimationHeightForRowAtIndexPath .. etc. J'ai essayé divers conseils sur StackOverflow. Rien ne semble fonctionner.
J'ai joint un exemple de projet très simple, où vous pouvez l'essayer vous-même:
https://www.dropbox.com/s/8f1rvkx9k23q6c1/tableviewtest.zip?dl=0
À noter - cela se produit {not} _ si la cellule n'est pas visible lorsqu'elle est rechargée. S'il se situe au-dessus de ou en dessous du point de défilement actuel, tout fonctionne comme prévu.
Ce comportement semble être un bogue, ne serait-ce que pour reproduire cela sur iOS 9. Pour une autre raison, il n’est plus reproductible sur iOS 9. Je suis sûr que ce n’est pas très réconfortant.
Le problème provient principalement d’une estimation inexacte, comme @NickCatib a déclaré. Le mieux que vous puissiez faire sur iOS 8 est d’améliorer l’estimation. Une technique recommandée par de nombreux utilisateurs consiste à mettre en cache les hauteurs dans willDisplayCell
et à les utiliser lors d'appels ultérieurs à estimatedRowHeightAtIndexPath
.
Vous pourrez peut-être limiter le comportement en ne faisant rien pour que UITableView
supprime ses caches, par exemple en modifiant le contenu d'une cellule directement à l'aide de cellForRowAtIndexPath
plutôt qu'en utilisant le rechargement s'il est affiché à l'écran. Toutefois, cela ne vous aidera pas si vous devez réellement modifier la hauteur de la cellule.
J'ai peur de dire que le bogue ne peut pas être facilement corrigé dans une vue de table, car vous n'avez pas le contrôle de la mise en page. Le bogue peut être plus facilement contourné dans une sous-classe UICollectionViewFlowLayout
en changeant la contentOffsetAdjustment
lors de l'invalidation, bien que cela puisse ne pas être terriblement facile.
J'avais aussi ce problème et utilisais une solution de SO que je suis incapable de trouver pour le moment. Si je le fais, je vais ajouter le lien. Voici la solution:
Le problème réside dans le fait que la vue tableau n'a pas l'estimation correcte pour la hauteur des lignes. Pour résoudre ce problème, mettez la hauteur en cache dans willDisplayCell
et utilisez cette hauteur la prochaine fois.
Code
Dans viewDidLoad:
heightAtIndexPath = [NSMutableDictionary new];
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
NSNumber *height = @(cell.frame.size.height);
[heightAtIndexPath setObject:height forKey:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
if([heightAtIndexPath objectForKey:indexPath]) {
return [[heightAtIndexPath objectForKey:indexPath] floatValue];
} else {
return UITableViewAutomaticDimension;
}
}
Euh ... c'est un peu difficile à régler.
Jetons un coup d'oeil à facebook. Ils ont eu le même problème avec leur calendrier, et ils ont fini par le faire dans une sorte de vue Web.
J'ai eu un problème similaire avec une sorte de calendrier, utilisé la hauteur de ligne automatique et eu ce problème. La première chose à faire était de régler estimatedHeight
aussi près que possible de la hauteur moyenne des cellules. C'est assez difficile à gérer car vous pouvez avoir du texte (hauteur 50) ou des images + texte (hauteur 1500). La prochaine chose à faire avec l'amélioration de cette situation a été la mise en œuvre de estimatedHeight forIndexPath
qui renvoie fondamentalement différentes hauteurs estimées pour différents indexPaths.
Après cela, il y avait beaucoup d'autres solutions, mais c'était aussi proche que possible avec des hauteurs variables (énormes différences).