Ist es möglich, mithilfe des automatischen Layouts eine dynamische Kopfhöhe der Tabellenansicht zu erhalten?

112

Neu in iOS 8 können Sie 100% dynamische Tabellenansichtszellen erhalten, indem Sie einfach die geschätzte Zeilenhöhe festlegen und dann Ihre Elemente in der Zelle mithilfe des automatischen Layouts anordnen. Wenn der Inhalt an Höhe zunimmt, nimmt auch die Höhe der Zelle zu. Dies ist äußerst nützlich und ich frage mich, ob das gleiche Kunststück für Abschnittsüberschriften in einer Tabellenansicht erreicht werden kann.

Kann man beispielsweise ein UIViewIn erstellen tableView:viewForHeaderInSection:, eine UILabelUnteransicht hinzufügen , Einschränkungen für das automatische Layout des Etiketts für die Ansicht festlegen und die Höhe der Ansicht erhöhen, um sie an den Inhalt des Etiketts anzupassen, ohne sie implementieren zu müssen tableView:heightForHeaderInSection:?

Die Dokumentation für viewForHeaderInSectionZustände: "Diese Methode funktioniert nur dann korrekt, wenn tableView: heightForHeaderInSection: ebenfalls implementiert ist." Ich habe nicht gehört, ob sich für iOS 8 etwas geändert hat.

Wenn man das nicht kann, wie kann man dieses Verhalten am besten nachahmen?

Jordan H.
quelle

Antworten:

274

Das ist möglich. Es ist neu neben den dynamischen Zellenhöhen, die in iOS 8 implementiert sind.

Es ist sehr einfach. Fügen Sie dies einfach hinzu viewDidLoad:

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

Überschreiben Sie dann viewForHeaderInSectionund verwenden Sie das automatische Layout, um Elemente in Ihrer Ansicht nach eigenem Ermessen einzuschränken. Das ist es! Keine Notwendigkeit zu implementieren heightForHeaderInSection. Und eigentlich muss das sectionHeaderHeightauch nicht angegeben werden, ich habe es nur der Klarheit halber hinzugefügt.

Beachten Sie, dass in iOS 11 Zellen und Kopf- / Fußzeilenansichten standardmäßig geschätzte Höhen verwenden. Sie müssen lediglich eine geschätzte Höhe angeben, um das System besser darüber zu informieren, was zu erwarten ist. Der Standardwert ist, UITableViewAutomaticDimensionaber Sie sollten eine bessere Schätzung angeben, die der durchschnittlichen Höhe entspricht, die sie nach Möglichkeit haben werden.

Jordan H.
quelle
3
Das ist cool, wenn es funktioniert, aber die Dokumente erwähnen es nicht und die WWDC-Sitzung auch nicht, wenn ich mich richtig erinnere. In den Dokumenten UITableViewAutomaticDimensionheißt es: "Wenn Sie diese Konstante in tableView:heightForHeaderInSection:oder zurückgeben tableView:heightForFooterInSection:, UITableViewwird eine Höhe verwendet, die dem von tableView:titleForHeaderInSection:oder zurückgegebenen Wert entspricht tableView:titleForFooterInSection:(wenn der Titel nicht lautet nil)."
Aaron Brager
28
Das hat bei mir nicht funktioniert. Mein Abschnittskopf konnte die Höhe automatisch berechnen, überlappt jedoch die Zellen im Abschnitt. Ich richte meine Header-Ansicht mithilfe einer XIB-Datei ein und setze meine Einschränkungen im Interface Builder. Ist das mein Problem? Wo schafft ihr die Einschränkungen? Vielen Dank!
CoBrA2168
5
Wie hier versprochen ist der Beispielcode: github.com/ebetabox/DynamicCellSectionHeight
PakitoV
10
Ein weiterer wichtiger Punkt ist, dass Ihre Tabellenzellen auch für die Berechnung der automatischen Höhe (UITableViewAutomaticDimension) konfiguriert werden müssen, damit sie in den Abschnitten funktionieren.
Bob Spryn
9
Sie müssen estimatedSectionHeaderHeightoder tableView:estimatedHeightForHeaderInSection:UND sectionHeaderHeightoder haben tableView:heightForHeaderInSection:. Wenn Sie die Delegatmethoden verwenden, müssen Sie außerdem einen Wert größer als 1,00 für die Schätzung zurückgeben (vollständig undokumentiertes Verhalten). Andernfalls wird der Delegat für die Höhe NICHT aufgerufen und die Standardhöhe der Tabellenansicht wird verwendet.
Vadoff
29

Dies kann erreicht werden, indem estimatedSectionHeaderHeightSie die Ansicht in Ihrer Tabelle festlegen (oder zurückgeben) .

Wenn sich Ihre Abschnittsüberschrift nach dem Festlegen mit Ihren Zellen überlapptestimatedSectionHeaderHeight , stellen Sie sicher, dass Sie auch eine verwenden estimatedRowHeight.

(Ich füge diese Antwort hinzu, da der zweite Absatz eine Antwort auf ein Problem enthält, das nach dem Lesen aller Kommentare gefunden werden kann, die einige möglicherweise übersehen.)

Clay Ellis
quelle
1
Danke, nach dem Einstellen estimatedRowHeightfunktioniert dies wie Charme :)
sz ashik
1
Dies gilt auch dann, wenn Sie UITableViewAutomaticDimension NICHT für Zeilen verwenden. Danke, dass du mir eine Stunde gespart hast.
Ryan Romanchuk
14

Ich bin in der gleichen Ausgabe hängen geblieben, in der der Header bis zu einer Höhe von Null wurde und es sei denn, ich gebe im Delegaten eine feste Höhe für an heighForHeaderInSection.

Versuchte viele Lösungen, einschließlich

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

Aber nichts hat funktioniert. Meine Zelle verwendete auch richtige Autolayouts. Zeilen änderten ihre Höhe dynamisch mithilfe des folgenden Codes, Abschnittsüberschriften jedoch nicht.

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

Das Update ist extrem einfach und auch seltsam, aber ich musste die Delegate-Methoden anstelle von 1 Zeilencode für das estimatedSectionHeaderHeightund implementieren, sectionHeaderHeightwas für meinen Fall wie folgt lautet.

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

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

Swift 4+

arbeiten (100% getestet)

Wenn Sie sowohl einen Abschnitt als auch eine Zeile mit dynamischer Höhe basierend auf dem Inhalt benötigen, können Sie den folgenden Code verwenden:

Schreiben Sie auf viewDidLoad () folgende Zeilen:

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

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

Jetzt haben wir die Zeilenhöhe und die Abschnittshöhe mithilfe der UITableView Delegate-Methoden festgelegt:

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

       return UITableView.automaticDimension

   }
Mr.Javed Multani
quelle
HINWEIS zu dieser großartigen Antwort. Ab 2020 scheint es in Ordnung zu sein, NUR die vier Eigenschaften in viewDidLoad zu verwenden.
Fattie
HINWEIS zu dieser großartigen Antwort. Ab 2020 benötigen Sie die beiden "nutzlosen" Linien mit einer geschätzten Höhe (z. B. 20 oder so).
Fattie
6

Ich habe es versucht

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

Der Header mit mehrzeiliger Beschriftung wurde jedoch nicht richtig dimensioniert. Fügte dies hinzu, um mein Problem zu lösen:

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

    // Recalculates height
    tableView.beginUpdates()
    tableView.endUpdates()
}
iuriimoz
quelle
Definieren Sie die Datenquellenfunktionen tableView:estimatedHeightForHeaderInSectionund tableView:heightForHeaderInSectionanstatt sie bei viewDidLoad zu definieren.
Keith Yeoh
Ich fand Einstellung estimatedSectionHeaderHeightist nur unter iOS 11 erforderlich
doctorBroctor
1

In meinem Fall:

  1. programmgesteuert nicht funktionieren .

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension.

  1. Set im Storyboard funktioniert nicht .

  2. Überschreiben heightForHeaderInSection funktioniert .

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

Testumgebung:

  • Mac OS 10.13.4
  • XCode Version 9.4.1
  • Simulator iPhone 8 Plus
Codus
quelle
0

Ja, das funktioniert bei mir. Ich muss weitere Änderungen wie folgt vornehmen:

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

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

    return label
}
arg_vn
quelle
-2

Ich habe die Antwort von iuriimoz geändert . Gerade die viewWillAppear-Methode ersetzt:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 25


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

    // Recalculates height
    tableView.layoutIfNeeded() 
}

Fügen Sie außerdem tableView.layoutIfNeeded () hinzu

override func viewDidAppear(_ animated: Bool) {

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

Für iOS 10

tableView.beginUpdates()
tableView.endUpdates()

habe für mich einen "Fade" -Animationseffekt auf viewWillAppear

Irina
quelle