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

112

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

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

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

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

Jordan H
источник

Ответы:

275

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

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

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

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

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

Jordan H
источник
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
Codus
источник
0

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

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

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

    return label
}
arg_vn
источник
-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()

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

Ирина
источник