13

Je rencontre un problème avec les vues d'en-tête de section UITableView automatiques/dynamiques qui contiennent un UILabel qui enveloppe (numberOfLines = 0). La hauteur n'est pas calculée correctement, en particulier lorsque vous faites défiler la table et que les vues sont réutilisées. Parfois, UILabel enveloppe, parfois il est tronqué, parfois une ou plusieurs des étiquettes ne sont pas visibles, et parfois il y a un espacement supplémentaire entre les étiquettes. La vue personnalisée contient un UIStackView vertical avec trois UILabels, dont une fois enveloppe.Taille de l'en-tête de section UITableView La hauteur automatique n'est pas correctement mise à jour

Un exemple d'application complète illustrant le problème peut être trouvé au https://github.com/outerstorm/tableviewHeaderTest.

Les hauteurs d'en-tête de section se règlent automatiquement en viewDidLoad ce qui suit:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension 
    tableView.estimatedSectionHeaderHeight = 30.0 

et ont également mis en œuvre le heightForHeaderInSection suivant juste pour essayer de le faire fonctionner:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 
    return UITableViewAutomaticDimension 
} 

Je a également essayé d'appeler setNeedsLayout() et layoutIfNeeded() à divers points en vain. Toutes les suggestions seraient grandement appréciées.

Voici une capture d'écran du comportement vu dans l'application. La première section est coupure et la deuxième section est trop grand:

enter image description here

Répondre

1

En général

heightForHeaderInSection 

toujours appelé avant

viewForHeaderInSection 

lors de l'utilisation UITableViewAutomaticDimension, la hauteur de sectionheader ne calculer une fois appelée à moins tableview.reloadData() manuellement.

Dans le code, vous modifiez le texte de l'en-tête de section à chaque fois. la hauteur a été calculée à la première fois, et ne change pas automatiquement.

vous pouvez modifier la configuration func à:

func setup(someNum: Int) { 

    let text = String(repeating: "This is where the really long text goes so that it will wrap lines appropriately", count: someNum) 

    mainLabel.text = text 
} 

et passer l'indice de section à la fonction

+0

Cela ne correspond pas à la virtualisation. Les cellules sont désactivées et doivent être redimensionnées chaque fois que cela se produit. Si ce n'est pas le cas, la virtualisation est cassée. – Tim

1

J'ai fait face à ce genre de question récemment.

Je l'ai résolu en mettant preferredMaxLayoutWidth des étiquettes multilignes, à savoir

Avant de régler la valeur dans les étiquettes, définissez leur preferredMaxLayoutWidth comme:

self.label1.preferredMaxLayoutWidth = self.label1.frame.size.width 
self.label2.preferredMaxLayoutWidth = self.label2.frame.size.width 
self.label3.preferredMaxLayoutWidth = self.label3.frame.size.width 
+0

J'ai essayé cela et je n'ai vu aucun changement de comportement. Le problème est toujours présent dans l'exemple d'application. – outerstorm

2

Il suffit d'ajouter la fonction estimatedHeightForHeaderInSection et retourner votre hauteur estimée. Cela résoudra votre problème.Téléchargez votre projet modifié de here

func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat 
{ 
    return 30; 
} 
+0

Je n'ai vu aucun changement de comportement avec ou sans cela. – outerstorm

+0

Cela semble fonctionner correctement sans aucun problème pour moi dans 10.3.2. Quelle est votre version d'ios? –

+0

Aussi 10.3.2. J'ai mis à jour la question avec une capture d'écran avec le comportement de l'application exemple. En outre, l'exemple d'application a été mis à jour sur github avec les correctifs suggérés. – outerstorm

1

Une solution peut être tenir les vues d'en-tête en tableau et puis retourner la hauteur de vue de la méthode estimée de hauteur

for _ in 0 ..< data.count { 

     let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "CustomHeaderView") as! CustomHeaderView 
     view.setup() 
     headerViews.append(view) 
    } 


func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat 
{ 
    let view = headerViews[section] as? UIView 
    return (view?.frame.size.height)! 
} 

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 

    return headerViews[section] as? UIView 
} 
+0

Bien que cela fonctionne probablement, il tue la virtualisation. Ce qui équivaut à 50% de la raison d'utiliser les vues de table! – Tim

0

Ajouter self.label1.preferredMaxLayoutWidth = self.label1.frame.size.width self.label1.numberoflines = 0; self.label1.linebreakmode = NSLineBreakByWordWrapping; dans la méthode awakeFromNib ou Veuillez le vérifier une fois https://github.com/krishnasolankiD/multiLineLabel