web-dev-qa-db-fra.com

Hauteur automatique de l'en-tête de section UITableView non mise à jour correctement

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 le tableau et que les vues sont réutilisées. Parfois, UILabel est renvoyé à la ligne, parfois tronqué, parfois une ou plusieurs étiquettes ne sont pas visibles, et parfois un espacement supplémentaire existe entre les étiquettes. La vue personnalisée contient une UIStackView verticale avec trois UILabels, dont une enveloppe.

Vous trouverez un exemple complet d'application démontrant le problème à l'adresse https://github.com/outerstorm/tableviewHeaderTest .

Les hauteurs d'en-tête de section sont définies sur automatique dans viewDidLoad avec les éléments suivants:

    tableView.sectionHeaderHeight = UITableViewAutomaticDimension
    tableView.estimatedSectionHeaderHeight = 30.0

et ont également implémenté le heightForHeaderInSection suivant juste pour essayer de le faire fonctionner:

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

J'ai également essayé d'appeler setNeedsLayout () et layoutIfNeeded () à plusieurs reprises sans succès. Toutes les suggestions seraient grandement appréciées.

Vous trouverez ci-dessous une capture d'écran du comportement observé dans l'application. La première section est coupée et la deuxième section est trop grande:

 enter image description here

14
outerstorm

Ajoutez simplement la fonction estimatedHeightForHeaderInSection et renvoyez votre hauteur estimée. Cela résoudra votre problème. Téléchargez votre projet modifié de ici

func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat 
{
    return 30;
}
2
Jaffer Sheriff

J'ai fait face à ce genre de problème récemment. 

Je l'ai résolu en définissant preferredMaxLayoutWidth d'étiquettes multilignes, c'est-à-dire.

Avant de définir la valeur dans les étiquettes, définissez leur preferredMaxLayoutWidth comme suit:

self.label1.preferredMaxLayoutWidth = self.label1.frame.size.width
self.label2.preferredMaxLayoutWidth = self.label2.frame.size.width
self.label3.preferredMaxLayoutWidth = self.label3.frame.size.width
1
PGDev

Une solution de contournement peut être de conserver les vues d'en-tête dans un tableau, puis de renvoyer la hauteur de vue à partir de la méthode de hauteur estimée

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
}
1
Anuj Panwar

En général

heightForHeaderInSection

toujours appelé avant

viewForHeaderInSection

lors de l'utilisation de UITableViewAutomaticDimension, la hauteur de l'en-tête de section ne sera calculée qu'une fois, à moins d'être appelée manuellement tableview.reloadData ().

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 fonction de configuration pour:

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 passez l'index de section à la fonction

1
weikel

De la documentation du code:

// Returning this value from tableView:heightForHeaderInSection: or tableView:heightForFooterInSection: results in a height that fits the value returned from // tableView:titleForHeaderInSection: or tableView:titleForFooterInSection: if the title is not nil.

En d'autres termes. UITableViewAutomaticDimension est uniquement destiné à être utilisé si vous fournissez un titre de section utilisant titleForHeaderInSection ou titleForFooterInSection

0
Alex Chase

Ajoutez la méthode self.label1.preferredMaxLayoutWidth = self.label1.frame.size.width self.label1.numberoflines = 0; self.label1.linebreakmode = NSLineBreakByWordWrapping;in dans awakeFromNib Ou Veuillez vérifier cette option une fois https://github.com/krishnasolankiD/multiLineLabel

0
krishna solanki