Как подделать стили заголовков раздела списка по умолчанию в iOS 15

С выпуском iOS 15 вы могли заметить, что стиль заголовка списка немного изменился. Теперь у него значительно больше отступов над и под разделом. Вы можете увидеть сравнение ниже.

Список iOS 14 и список iOS 15

Если вы не являетесь поклонником этого изменения, вы можете изменить верхнее заполнение заголовков, изменив свойство sectionHeaderTopPadding на UITableView, или если вы похожи на меня и перешли на SwiftUI, тогда вы можете использовать внешний вид модификатор примерно так:

UITableView.appearance().sectionHeaderTopPadding = 0

Это все прекрасно, если вы хотите использовать списки в своем приложении. Вы получаете (возможно) хорошую настройку пользовательского интерфейса для списков, в основном бесплатно. Но недавно я столкнулся с интересной проблемой, пытаясь воспроизвести новый стиль.

Репликация заголовков разделов iOS

Вы спросите, зачем вам это повторять? Что ж, во время работы над моим последним проектом (Флора — посмотрите здесь) мне также нужно было использовать сетку в моем приложении. У меня был ScrollView с LazyVGrid внутри него с кучей ячеек, которые нужно было разделить на разделы по категориям.

Без контекста списка заголовки разделов по умолчанию имеют совершенно другой размер и вес шрифта. С тем же содержимым списка, что и в первом примере, вы можете видеть, что заголовки «Фрукты» и «Овощи» теперь по умолчанию имеют тот же текст по умолчанию, что и обычное представление Text.

Я хотел сохранить единый стиль заголовка для обоих представлений List, а также для любых представлений ScrollView или LazyVGrid. Поскольку пользователь, скорее всего, уже знаком с заголовками в стиле iOS, я подумал, что лучше всего попробовать смоделировать заголовок в стиле iOS.

… Но есть проблема

Легче сказать, чем сделать, поскольку документация Apple, включая представления SwiftUI и UIKit List/ UITableView, не предоставляет никакой полезной информации об отступах, шрифтах или цветах по умолчанию.

Согласно документам Apple, значение по умолчанию для sectionHeaderTopPadding равно UITableViewAutomaticDimension. Apple Documentation
Это нам не поможет, потому что ни официальная документация, ни изучение заголовочного файла не дают нам никакой полезной информации. Это должно быть определено во время выполнения на основе контекста представления. Также не упоминается размер шрифта по умолчанию, вес шрифта или цвет шрифта для заголовков.

Поскольку официального источника значений по умолчанию нет, нам приходится прибегать к методу проб и ошибок. Сначала я создал обычный старый список в SwiftUI, запустил его на симуляторе и сделал скриншот. Теперь у нас есть базовый уровень для сравнения с нашей собственной реализацией.

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

Затем я начал тестировать значения отступов над текстом, делая скриншоты по мере продвижения, пока не получил результаты, которые находились в пределах нескольких пикселей друг от друга. В тот момент я знал, что нашел значение, которое более или менее соответствует реализации Apple.

Цвет шрифта довольно четко Color.secondary, который, казалось, точно совпал. Затем для размера шрифта, больше проб и ошибок. Шрифт, который, казалось, наиболее подходил, имел размер 13 пунктов и толщину шрифта .regular.

Реализация

Собрав все это вместе, мы можем создать общее представление, которое издевается над реализацией Apple.

Вот все значения, которые я нашел методом проб и ошибок

  • Цвет шрифта: Color.secondary
  • Размер шрифта: 13 Points
  • Вес шрифта: .regular
  • Начальное заполнение (заполнение с левой стороны строки списка): 14
  • Верхняя обивка: 12
  • Нижняя прокладка: 8

Поместив все эти значения в красивое общее представление, мы получим что-то вроде этого:

Затем вы можете использовать это представление в своем собственном ScrollView примерно так:

Section(header: MockedSectionHeader(header: "Fruits")) {
    Text("Apple")
    Text("Orange")
    Text("Pear")
}

Возможно, вам придется добавить отступы к сторонам LazyVGrid или ScrollView, которые вы используете, чтобы соответствовать отступу List, но теперь мы максимально приблизились к стилю заголовка iOS.

Это было полезно в моем собственном проекте, поэтому, если у вас возникла та же проблема, надеюсь, я сэкономил вам время на гугление и возню.

Спасибо за прочтение.