Est-il possible d'obtenir une hauteur d'en-tête de section de vue tableau dynamique à l'aide de la disposition automatique?

112

Nouveau dans iOS 8, vous pouvez obtenir des cellules de vue de tableau 100% dynamiques en définissant simplement la hauteur de ligne estimée, puis en mettant en page vos éléments dans la cellule à l'aide de la disposition automatique. Si le contenu augmente en hauteur, la cellule augmentera également en hauteur. Ceci est extrêmement utile et je me demande si le même exploit peut être accompli pour les en-têtes de section dans une vue de tableau?

Peut-on, par exemple, créer un UIViewin tableView:viewForHeaderInSection:, ajouter une sous- UILabelvue, spécifier des contraintes de mise en page automatique pour l'étiquette par rapport à la vue et faire augmenter la hauteur de la vue pour s'adapter au contenu de l'étiquette, sans avoir à implémenter tableView:heightForHeaderInSection:?

La documentation pour les viewForHeaderInSectionétats: "Cette méthode ne fonctionne correctement que lorsque tableView: heightForHeaderInSection: est également implémentée." Je n'ai pas entendu si quelque chose a changé pour iOS 8.

Si on ne peut pas faire cela, quelle est la meilleure façon d'imiter ce comportement?

Jordanie H
la source

Réponses:

275

C'est possible. C'est nouveau juste à côté des hauteurs de cellules dynamiques implémentées dans iOS 8.

C'est très simple. Ajoutez simplement ceci dans viewDidLoad:

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 25;

Remplacez ensuite viewForHeaderInSectionet utilisez la disposition automatique pour contraindre les éléments de votre vue comme vous le souhaitez. C'est tout! Pas besoin de mettre en œuvre heightForHeaderInSection. Et en fait, il sectionHeaderHeightn'est pas nécessaire non plus de l'indiquer, je l'ai simplement ajouté pour plus de clarté.

Notez que dans iOS 11, les cellules et les vues d'en-tête / pied de page utilisent des hauteurs estimées par défaut. La seule chose à faire est de fournir une hauteur estimée pour mieux informer le système à quoi s'attendre. La valeur par défaut est, UITableViewAutomaticDimensionmais vous devez fournir une meilleure estimation de la hauteur moyenne qu'ils auront si possible.

Jordanie H
la source
3
C'est cool si cela fonctionne, mais les documents ne le mentionnent pas, et la session WWDC non plus si je me souviens bien. La documentation pour UITableViewAutomaticDimensiondire "si vous renvoyez cette constante dans tableView:heightForHeaderInSection:ou tableView:heightForFooterInSection:, UITableViewutilise une hauteur qui correspond à la valeur renvoyée par tableView:titleForHeaderInSection:ou tableView:titleForFooterInSection:(si le titre ne l'est pas nil)".
Aaron Brager
28
Cela n'a pas fonctionné pour moi. Mon en-tête de section a pu calculer la hauteur automatiquement, mais il chevauche les cellules de la section. Je configure ma vue d'en-tête à l'aide d'un fichier xib et je définis mes contraintes dans le générateur d'interface. Est-ce mon problème? Où créez-vous les contraintes? Merci!
CoBrA2168
5
Comme promis, voici l'exemple de code: github.com/ebetabox/DynamicCellSectionHeight
PakitoV
10
Autre point clé ici, les cellules de votre tableau doivent également être configurées pour le calcul automatique de la hauteur (UITableViewAutomaticDimension) pour que cela fonctionne sur les sections.
Bob Spryn
9
Vous devez avoir estimatedSectionHeaderHeightou tableView:estimatedHeightForHeaderInSection:ET sectionHeaderHeightou tableView:heightForHeaderInSection:. En outre, si vous utilisez les méthodes de délégué, vous devez renvoyer une valeur supérieure à 1,00 pour l'estimation (comportement complètement non documenté), sinon le délégué pour la hauteur ne sera PAS appelé et la hauteur d'en-tête de vue de table par défaut sera utilisée.
Vadoff
29

Cela peut être accompli en définissant (ou en retournant) la vue estimatedSectionHeaderHeightsur votre table.

Si votre en-tête de section chevauche vos cellules après la configurationestimatedSectionHeaderHeight , assurez-vous que vous utilisez également un estimatedRowHeight.

(J'ajoute cette réponse car le deuxième paragraphe contient une réponse à un problème qui peut être trouvé après avoir lu tous les commentaires que certains pourraient manquer.)

Clay Ellis
la source
1
Merci, après avoir réglé estimatedRowHeightcela fonctionne comme un charme :)
sz ashik
1
Cela est vrai même si vous n'utilisez PAS UITableViewAutomaticDimension pour les lignes. Merci de m'avoir économisé une heure.
Ryan Romanchuk
14

Je suis resté coincé dans le même problème où l'en-tête obtenait une hauteur nulle jusqu'à ce que je fournisse une hauteur fixe dans le délégué pour heighForHeaderInSection .

J'ai essayé de nombreuses solutions, notamment

self.tableView.sectionHeaderHeight = UITableView.automaticDimension
self.tableView.estimatedSectionHeaderHeight = 73

Mais rien n'a fonctionné. Ma cellule utilisait également des mises en page automatiques appropriées. Les lignes changeaient leur hauteur dynamiquement en utilisant le code suivant, mais pas l'en-tête de section.

self.tableView.estimatedRowHeight = 135
self.tableView.rowHeight = UITableView.automaticDimension

Le correctif est extrêmement simple et étrange aussi, mais j'ai dû implémenter les méthodes de délégué au lieu d'un code de ligne pour le estimatedSectionHeaderHeightet sectionHeaderHeightqui va comme suit pour mon cas.

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

func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
    73
}
Ahsan Ebrahim
la source
11

Swift 4+

travail (testé à 100%)

Si vous avez besoin des deux sections ainsi que des lignes avec une hauteur dynamique basée sur le contenu, vous pouvez utiliser le code ci-dessous:

Sur viewDidLoad (), écrivez ces lignes:

    self.globalTableView.estimatedRowHeight = 20
    self.globalTableView.rowHeight = UITableView.automaticDimension

    self.globalTableView.sectionHeaderHeight =  UITableView.automaticDimension
    self.globalTableView.estimatedSectionHeaderHeight = 25;

Nous avons maintenant défini la hauteur de ligne et la hauteur de section à l'aide des méthodes UITableView Delegate:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
   {
       return UITableView.automaticDimension
   }
   func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {

       return UITableView.automaticDimension

   }
Monsieur Javed Multani
la source
NOTE à cette excellente réponse. À partir de 2020, il semble être acceptable d'utiliser UNIQUEMENT les quatre propriétés de viewDidLoad.
Fattie le
NOTE à cette excellente réponse. À partir de 2020, vous avez besoin des deux lignes "inutiles" donnant une hauteur estimée (disons, 20 environ).
Fattie le
6

j'ai essayé

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 25;

mais il n'a pas correctement dimensionné l'en-tête avec l'étiquette multiligne. Ajouté ceci pour résoudre mon problème:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Recalculates height
    tableView.beginUpdates()
    tableView.endUpdates()
}
iuriimoz
la source
définissez les fonctions de source de données tableView:estimatedHeightForHeaderInSectionet tableView:heightForHeaderInSectionau lieu de définir à viewDidLoad.
Keith Yeoh
J'ai trouvé que le réglage estimatedSectionHeaderHeightn'est nécessaire que sous iOS 11
doctorBroctor
1

Dans mon cas:

  1. définir par programme ne fonctionne pas .

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension.

  1. mis en storyboard ne fonctionne pas .

  2. le remplacement a heightForHeaderInSection fonctionné .

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

environnement de test:

  • Mac OS 10.13.4
  • XCode version 9.4.1
  • Simulateur iPhone 8 Plus
Codus
la source
0

Oui, ça marche pour moi. Je dois faire plus de changements comme ci-dessous:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let label = UILabel()

    label.numberOfLines = 0
    label.text          = my own text

    return label
}
arg_vn
la source
-2

J'ai modifié la réponse iuriimoz . Vient de remplacer la méthode viewWillAppear:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 25


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Recalculates height
    tableView.layoutIfNeeded() 
}

Ajoutez également tableView.layoutIfNeeded () à

override func viewDidAppear(_ animated: Bool) {

    super.viewDidAppear(animated)
    tableView.layoutIfNeeded()
}

Pour iOS 10

tableView.beginUpdates()
tableView.endUpdates()

avoir un effet d'animation "fondu" sur la vue apparaîtra pour moi

Irina
la source