Czy można uzyskać dynamiczną wysokość nagłówka sekcji widoku tabeli przy użyciu funkcji Auto Layout?

112

Nowość w iOS 8, możesz uzyskać w 100% dynamiczne komórki widoku tabeli, po prostu ustawiając szacowaną wysokość wiersza, a następnie rozmieszczając elementy w komórce za pomocą automatycznego układu. Jeśli zawartość wzrośnie, wysokość komórki również wzrośnie. Jest to niezwykle przydatne i zastanawiam się, czy to samo można osiągnąć dla nagłówków sekcji w widoku tabeli?

Czy można na przykład utworzyć widok UIViewin tableView:viewForHeaderInSection:, dodać UILabelwidok podrzędny, określić ograniczenia automatycznego układu etykiety względem widoku i zwiększyć wysokość widoku, aby dopasować go do zawartości etykiety, bez konieczności implementacji tableView:heightForHeaderInSection:?

Dokumentacja dotycząca viewForHeaderInSectionstanów: „Ta metoda działa poprawnie tylko wtedy, gdy zaimplementowano również tableView: heightForHeaderInSection:”. Nie słyszałem, czy coś się zmieniło na iOS 8.

Jeśli nie można tego zrobić, jaki jest najlepszy sposób naśladowania tego zachowania?

Jordan H.
źródło

Odpowiedzi:

275

To jest możliwe. Jest nowy, obok dynamicznych wysokości komórek zaimplementowanych w iOS 8.

To jest bardzo proste. Po prostu dodaj to w viewDidLoad:

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

Następnie nadpisz viewForHeaderInSectioni użyj automatycznego układu, aby ograniczyć elementy w widoku zgodnie z dopasowaniem. Otóż ​​to! Nie ma potrzeby wdrażania heightForHeaderInSection. I właściwie sectionHeaderHeightnie trzeba też tego mówić, dodałem to dla jasności.

Zwróć uwagę, że w iOS 11 komórki i widoki nagłówka / stopki domyślnie używają szacunkowych wysokości. Jedyne, co należy zrobić, to podać szacunkową wysokość, aby lepiej poinformować system, czego się spodziewać. Wartość domyślna to, UITableViewAutomaticDimensionale należy podać lepsze oszacowanie, czyli średnią wysokość, jaką będą miały, jeśli to możliwe.

Jordan H.
źródło
3
Fajnie, jeśli to działa, ale doktorzy o tym nie wspominają, podobnie jak sesja WWDC, jeśli dobrze pamiętam. Dokumenty zawierające informację UITableViewAutomaticDimension„jeśli zwrócisz tę stałą w tableView:heightForHeaderInSection:lub tableView:heightForFooterInSection:, UITableViewużyje wysokości pasującej do wartości zwróconej z tableView:titleForHeaderInSection:lub tableView:titleForFooterInSection:(jeśli tytuł nie jest nil)”.
Aaron Brager
28
To nie zadziałało dla mnie. Mój nagłówek sekcji mógł automatycznie obliczyć wysokość, ale nakłada się na komórki w sekcji. Konfiguruję widok nagłówka za pomocą pliku xib i ustawiam ograniczenia w konstruktorze interfejsu. Czy to mój problem? Gdzie jesteście tworzący ograniczenia? Dzięki!
CoBrA2168,
5
Zgodnie z obietnicą jest tutaj przykładowy kod: github.com/ebetabox/DynamicCellSectionHeight
PakitoV
10
Kolejna kluczowa kwestia, komórki tabeli muszą również zostać skonfigurowane do automatycznego obliczania wysokości (UITableViewAutomaticDimension), aby działało na sekcjach.
Bob Spryn
9
Musisz mieć estimatedSectionHeaderHeightlub tableView:estimatedHeightForHeaderInSection:AND sectionHeaderHeightlub tableView:heightForHeaderInSection:. Ponadto, jeśli używasz metod delegata, musisz zwrócić wartość większą niż 1,00 dla oszacowania (całkowicie nieudokumentowane zachowanie), w przeciwnym razie delegat wysokości NIE zostanie wywołany i zostanie użyta domyślna wysokość nagłówka widoku tabeli.
Vadoff
29

Można to osiągnąć, ustawiając (lub zwracając) estimatedSectionHeaderHeightwidok tabeli.

Jeśli nagłówek sekcji nakłada się na komórki po ustawieniuestimatedSectionHeaderHeight , upewnij się, że używasz estimatedRowHeightrównież.

(Dodaję tę odpowiedź, ponieważ drugi akapit zawiera odpowiedź na problem, który można znaleźć po przeczytaniu wszystkich komentarzy, które niektórzy mogą przegapić.)

Clay Ellis
źródło
1
Dzięki, po ustawieniu estimatedRowHeightto działa jak urok :)
sz ashik
1
Dzieje się tak, nawet jeśli NIE używasz UITableViewAutomaticDimension dla wierszy. Dzięki za uratowanie mi godziny.
Ryan Romanchuk
14

Utknąłem w tym samym problemie, w którym nagłówek uzyskiwał zerową wysokość do i chyba że podam stałą wysokość w delegacie dla heighForHeaderInSection.

Wypróbowałem wiele rozwiązań, w tym

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

Ale nic nie działało. Moja komórka też korzystała z odpowiednich autoukładów. Wiersze dynamicznie zmieniały wysokość za pomocą poniższego kodu, ale nagłówek sekcji nie.

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

Poprawka jest niezwykle prosta i dziwna, ale musiałem zaimplementować metody delegatów zamiast 1-wierszowego kodu dla estimatedSectionHeaderHeighti, sectionHeaderHeightco w moim przypadku wygląda następująco.

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

func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
    73
}
Ahsan Ebrahim
źródło
11

Swift 4+

działa (testowane w 100%)

Jeśli potrzebujesz zarówno sekcji, jak i wiersza z dynamiczną wysokością opartą na zawartości, możesz użyć poniższego kodu:

W viewDidLoad () napisz te linie:

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

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

Teraz ustawiliśmy wysokość wiersza i wysokość sekcji za pomocą metod delegata UITableView:

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

       return UITableView.automaticDimension

   }
Panie Javed Multani
źródło
UWAGA do tej wspaniałej odpowiedzi. Od 2020 roku wydaje się, że można używać TYLKO czterech właściwości w viewDidLoad.
Fattie
UWAGA do tej wspaniałej odpowiedzi. Od 2020 roku potrzebujesz dwóch „bezużytecznych” linii podających szacunkową wysokość (powiedzmy około 20).
Fattie
6

próbowałem

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

ale nagłówek z etykietą wielowierszową ma nieprawidłowy rozmiar. Dodano to, aby rozwiązać mój problem:

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

    // Recalculates height
    tableView.beginUpdates()
    tableView.endUpdates()
}
iuriimoz
źródło
zdefiniować funkcje źródła danych tableView:estimatedHeightForHeaderInSectioni tableView:heightForHeaderInSectionzamiast definiować w viewDidLoad.
Keith Yeoh,
Stwierdziłem, że ustawienie estimatedSectionHeaderHeightjest konieczne tylko poniżej iOS 11
doctorBroctor
1

W moim przypadku:

  1. ustawić programowo nie działa .

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension.

  1. ustawione w scenorysie nie działają .

  2. zastąpienie heightForHeaderInSection zadziałało .

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

środowisko testowe:

  • Mac OS 10.13.4
  • XCode w wersji 9.4.1
  • Symulator iPhone 8 Plus
Codus
źródło
0

Tak, to działa dla mnie. Muszę wprowadzić więcej zmian jak poniżej:

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

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

    return label
}
arg_vn
źródło
-2

Zmodyfikowałem odpowiedź iuriimoz . Właśnie zastąpiłem metodę viewWillAppear:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 25


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

    // Recalculates height
    tableView.layoutIfNeeded() 
}

Dodaj również metodę tableView.layoutIfNeeded () do

override func viewDidAppear(_ animated: Bool) {

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

Na iOS 10

tableView.beginUpdates()
tableView.endUpdates()

mają efekt animacji „zanikania” na widokuWillAppear for me

Irina
źródło