Можно ли получить высоту заголовка раздела динамического табличного представления с помощью Auto Layout?


112

Новое в iOS 8: вы можете получить 100% ячеек динамического табличного представления, просто установив предполагаемую высоту строки, а затем разместив свои элементы в ячейке с помощью Auto Layout. Если содержимое увеличивается в высоту, высота ячейки также увеличивается. Это чрезвычайно полезно, и мне интересно, можно ли сделать то же самое для заголовков разделов в табличном представлении?

Можно, например, создать UIViewв tableView:viewForHeaderInSection:добавить UILabelподвид, указать ограничение Автокомпоновки для метки с точкой зрения, и есть увеличение вида в высоту , чтобы соответствовать содержимому лейло, без необходимости реализовывать tableView:heightForHeaderInSection:?

В документации для viewForHeaderInSectionговорится: «Этот метод работает правильно только в том случае, если также реализован tableView: heightForHeaderInSection:». Я не слышал, изменилось ли что-нибудь в iOS 8.

Если это невозможно, как лучше всего имитировать такое поведение?

Ответы:


275

Это возможно. Это новинка наряду с динамической высотой ячеек, реализованной в iOS 8.

Все очень просто. Просто добавьте это в viewDidLoad:

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

Затем переопределите viewForHeaderInSectionи используйте Auto Layout, чтобы ограничить элементы в вашем представлении так, как вам кажется нужным. Это оно! Не нужно внедрять heightForHeaderInSection. И на самом делеsectionHeaderHeight тоже не нужно говорить, я просто добавил это для ясности.

Обратите внимание, что в iOS 11 для ячеек и представлений верхнего / нижнего колонтитула по умолчанию используется расчетная высота. Единственное, что нужно сделать, - это указать приблизительную высоту, чтобы лучше информировать систему, чего ожидать. Значение по умолчанию - UITableViewAutomaticDimensionно вы должны дать более точную оценку средней высоты, которой они будут, если это возможно.


3
Это круто, если это работает, но в документации об этом не упоминается, как и в сеансе WWDC, если я правильно помню. В документах UITableViewAutomaticDimensionговорится, что «если вы возвращаете эту константу в tableView:heightForHeaderInSection:или tableView:heightForFooterInSection:, UITableViewиспользуется высота, соответствующая значению, возвращаемому из tableView:titleForHeaderInSection:или tableView:titleForFooterInSection:(если заголовок не соответствует nil)».
Аарон Брагер

28
У меня это не сработало. В моем заголовке раздела высота была рассчитана автоматически, но он перекрывает ячейки в разделе. Я настраиваю представление заголовка с помощью файла xib и устанавливаю ограничения в построителе интерфейса. Это моя проблема? Где вы, ребята, создаете ограничения? Спасибо!
CoBrA2168

5
Как и было обещано, вот пример кода: github.com/ebetabox/DynamicCellSectionHeight
PakitoV

10
Еще один ключевой момент здесь: ваши ячейки таблицы также должны быть настроены для автоматического расчета высоты (UITableViewAutomaticDimension), чтобы он работал с разделами.
Боб Сприн,

9
У вас должно быть estimatedSectionHeaderHeightили tableView:estimatedHeightForHeaderInSection:И, sectionHeaderHeightили tableView:heightForHeaderInSection:. Кроме того, если вы используете методы делегата, вы должны вернуть значение больше 1,00 для оценки (полностью недокументированное поведение), в противном случае делегат для высоты НЕ будет вызываться и будет использоваться высота заголовка представления таблицы по умолчанию.
Vadoff

29

Этого можно добиться, установив (или вернув) estimatedSectionHeaderHeightвид таблицы.

Если заголовок раздела перекрывает ваши ячейки после настройкиestimatedSectionHeaderHeight , убедитесь, что вы также используете estimatedRowHeight.

(Я добавляю этот ответ, потому что второй абзац содержит ответ на проблему, которую можно найти после прочтения всех комментариев, которые некоторые могут пропустить.)


1
Спасибо, после настройки estimatedRowHeightэто работает как шарм :)
sz

1
Это верно, даже если вы НЕ используете UITableViewAutomaticDimension для строк. Спасибо, что сэкономили мне час.
Райан Романчук

14

Застрял в той же проблеме, когда заголовок получал нулевую высоту до тех пор, пока я не предоставил фиксированную высоту в делегате для heighForHeaderInSection.

Пробовал много решений, включая

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

Но ничего не вышло. В моей камере тоже использовались правильные автопластины. Строки меняли свою высоту динамически с помощью следующего кода, но заголовок раздела - нет.

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

Исправление чрезвычайно простое и странное, но мне пришлось реализовать методы делегата вместо однострочного кода для estimatedSectionHeaderHeightи, sectionHeaderHeightкоторый в моем случае выглядит следующим образом.

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

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

11

Swift 4+

рабочий (проверено 100%)

Если вам нужны оба раздела, а также строка с динамической высотой в зависимости от содержимого, вы можете использовать следующий код:

В viewDidLoad () напишите следующие строки:

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

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

Теперь мы установили высоту строки и высоту раздела с помощью методов делегата UITableView:

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

       return UITableView.automaticDimension

   }

ПРИМЕЧАНИЕ к этому отличному ответу. По состоянию на 2020 год, кажется, можно использовать ТОЛЬКО четыре свойства в viewDidLoad.
Fattie

ПРИМЕЧАНИЕ к этому отличному ответу. По состоянию на 2020 год вам ДЕЙСТВИТЕЛЬНО нужны две «бесполезные» линии, указывающие примерную высоту (скажем, 20 или около того).
Fattie

7

Я попытался

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

но заголовок не соответствует размеру многострочной метки. Добавил это, чтобы решить мою проблему:

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

    // Recalculates height
    tableView.beginUpdates()
    tableView.endUpdates()
}

определить функции источника данных tableView:estimatedHeightForHeaderInSectionи tableView:heightForHeaderInSectionвместо определения в viewDidLoad.
Кейт Йео

Я обнаружил, что настройка estimatedSectionHeaderHeightнеобходима только ниже iOS 11
doctorBroctor

1

В моем случае:

  1. установить программно не получится .

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension.

  1. установить в раскадровке не получится .

  2. переопределение heightForHeaderInSection сработало .

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

тестовая среда:

  • Mac OS 10.13.4
  • XCode версии 9.4.1
  • Симулятор iPhone 8 Plus

0

Да, у меня работает. Мне нужно внести больше изменений, как показано ниже:

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

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

    return label
}

-2

Я изменил ответ iuriimoz . Просто заменил метод viewWillAppear:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 25


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

    // Recalculates height
    tableView.layoutIfNeeded() 
}

Также добавьте tableView.layoutIfNeeded () в

override func viewDidAppear(_ animated: Bool) {

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

Для iOS 10

tableView.beginUpdates()
tableView.endUpdates()

иметь эффект "затухания" анимации при просмотре

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.