[Перевод] Автоматические размеры хедера и футера UITableView с AutoLayout

image

В этой статье я попытаюсь раскрыть некоторые причуды класса UITableView и покажу вам простой и самый простой способы реализовать представления верхнего и нижнего колонтитулов изменяемой высоты. Для меня простота, это когда дело доходит до написания кодом пользовательского интерфейса, но на самом деле заключается в том, чтобы не кодить никакого UI. В этой статье я буду максимально использовать interface builder:)
Я буду говорить о заголовках, но то же самое относится и к нижним колонтитулам.

image

Настройка TableView


Хедеры в табличном или простом стиле TableView ничем не отличаются от любых других строк UITableView. Настройка на самом деле довольно проста.

  • должны быть установлены sectionHeaderHeight и estimatedHeaderHeight.
  • UITableView.automaticDimension — это то, что позволяет AutoLayout вычислять высоту каждой ячейки во время выполнения.
  • estimatedHeaderHeight должен быть установлен для грубой оценки общей высоты его содержимого для отображения индикатора прокрутки.


Эти свойства могут быть установлены в инспекторе размеров при выборе TableView в вашей раскадровке.

image

Создание представления заголовка (Header View)


tableView(_: viewForHeaderInSection: ) должен возвращать экземпляр UIView, но угадайте, что? UITableViewCell является подклассом UIView. Это означает, что мы можем использовать нашу раскадровку, чтобы создать прототип ячейки, которая может быть удалена и возвращена из этой функции. На мой взгляд, это самый лучший способ объявить все ваши представления в одном месте, вместо множества xib-файлов, разбросанных по вашему проекту.

image

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

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

image

Чтобы вернуть представление, мы вызываем dequeueReusableCell(withIdentifier identifier: String) -> UITableViewCell?. Мы не используем разновидность функции forIndexPath:, потому что у нас не определен indexPath для строк заголовка. Кроме того, forIndexPath: утверждает, что идентификатор повторного использования определен для ячейки исключенной из очереди, чтобы предотвратить возврат nil. В нашем случае раздел может отображаться без заголовка.

guard let headerCell = tableView.dequeueReusableCell(withIdentifier: "header") else {
    return nil
}


Заголовки пустых разделов


По задумке, если хедер для раздела в табличном представлении в стиле группы не определен, framework отобразит пустое представление размером 30 пикселей. Apple решила, что было бы странно, если бы разные разделы выглядели как один. Но иногда мы просто хотим нарушить правила. :)

Чтобы обойти это, можно использовать константу CGFLOAT_MIN. Он представляет минимальное неотрицательное значение для CGFloat. Значение равно 1.17549435e-38F или 2.2250738585072014e-308 для 32-битного и 64-битного кода соответственно. В конце концов, это не ноль пикселей. С другой стороны, в простом табличном представлении высота заголовка может быть установлена на любое значение, большее или равное 0.

Для этого особого случая нам нужно использовать tableView(_:estimatedHeightForHeaderInSection:) и tableView(_:heightForHeaderInSection:). Как указано в документации, две функции должны быть реализованы для определения высоты настраиваемого представления.

Заключение


Я был озадачен, увидев так много хаков на StackOverflow от людей, желающих реализовать заголовки разной высоты. Это простой трюк, который я постоянно использую при работе с TableView, и надеюсь, что он будет таким же полезным для вас, как и для меня. Удачного кодирования! :)

© Habrahabr.ru