Используйте пользовательский макет потока , чтобы идеально управлять высотой заголовка в представлении коллекции с помощью функции Dynamic Type
.
Элемент заголовка рассматривается как дополнительный элемент для представления коллекции и referenceSizeForHeaderInSection
'метод' используется только для инициализации: он не вызывается с функцией Dynamic Type
. 101
В дальнейшем решение основано на методе layoutAttributesForElements
пользовательского макета, который сможет адаптировать высоту заголовка благодаря UIFontMetrics
scaledValue
.
Все, что запускается методом invalidateLayout
, вызываемым в traitCollectionDidChange
, запускается, когда пользователь изменяет размер шрифта. 10
ШАГ 1 ⟹ создайте простой пользовательский класс заголовка, например, следующим образом:
class MyHeaderClass: UICollectionReusableView {
override init(frame: CGRect) { super.init(frame: frame) }
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
}
ШАГ 2 ⟹ создайте новый пустой. xib добавляет повторно используемое представление и назовите его точно таким же именем, как и класс, к которому он относится: не забудьте изменить имя этого класса в регистре Identity Inspector
.
STEP 3 ⟹ XIB-файл в контроллере:
collectionView.register(UINib(nibName: collectionViewHeaderFooterReuseIdentifier bundle: nil),
forSupplementaryViewOfKind: UICollectionElementKindSectionHeader,
withReuseIdentifier:collectionViewHeaderFooterReuseIdentifier)
ШАГ 4 ⟹ поддерживает эту новую ячейку в вашем источнике данных (заголовок является дополнительным элементом для представления коллекции) :
func collectionView(_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String,
at indexPath: IndexPath) -> UICollectionReusableView {
if (kind == UICollectionView.elementKindSectionHeader) {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
withReuseIdentifier: collectionViewHeaderReuseIdentifier,
for: indexPath) as! MyHeader
headerView.myLabel.text = "Your Header Title"
return headerView
} else {
return UICollectionReusableView(frame: CGRect.null) }
}
... и в вашем делегате (это инициализирует размер заголовка и делает его видимым) :
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: headerHeight)
}
.. после добавления глобальный var headerHeight: CGFloat = 90.0
для инициализации.
ШАГ 5 ⟹ создайте пользовательский макет потока для адаптации высоты заголовка к новому размеру шрифта:
class FlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let layoutAttributes = super.layoutAttributesForElements(in: rect)
layoutAttributes?.forEach({ (attribute) in
if (attribute.representedElementKind == UICollectionView.elementKindSectionHeader) {
headerHeight = UIFontMetrics.default.scaledValue(for: 22.0)
attribute.frame.size.height = headerHeight
}
})
return layoutAttributes
}
}
Don ' не забудьте обновить раскадровку в Interface Builder
: STEP 6 ⟹ информировать контроллер о необходимости запуска обновления макета, когда пользователь изменяет размер шрифта:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
if (previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory) {
collectionView?.collectionViewLayout.invalidateLayout()
}
}
Следуя этому обоснованию, автоматически устанавливается правильная высота заголовков в соответствии с размером шрифта заголовков ⟹ Я предлагаю использовать Новая функция Xcode 11 для очень быстрого тестирования Dynamic Type
. ?