I have a collectionView with a header designed in a .xib file. It has a simple label and it's text supports dynamicType.
How can I set the height of that header to be dynamic based on that label and the auto layout constraints in Storyboard?
So far, I've got this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
let kind = UICollectionView.elementKindSectionHeader
let indexPath = IndexPath(row: 0, section: section)
if let headerView = collectionView.supplementaryView(forElementKind: kind, at: indexPath) as? SectionHeaderView {
headerView.layoutIfNeeded()
headerView.setNeedsLayout()
let size = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
return size
}
return CGSize(width: 0, height: 0)
}
But it does not show any header.
SectionHeaderView.xib looks like this:
CollectionView looks like this: you see 3 sections, but you don't see a header.
What can I do to let AutoLayout determine the correct hight of the header?
Use a custom flow layout to perfectly manage the height of a header in a collection view with the
Dynamic Type
feature.A header element is seen as a supplementary element for a collection view and the
referenceSizeForHeaderInSection
'method' is only used for initialization: it's not called with theDynamic Type
feature.The solution hereafter is based on the
layoutAttributesForElements
method of the custom layout that will be able to adapt the header height thanks to theUIFontMetrics
scaledValue
.All that is fired by the
invalidateLayout
method called in thetraitCollectionDidChange
triggered when the user changes the font size.STEP 1 ⟹ create a simple custom header class as follows for instance:
STEP 2 ⟹ create a new empty .xib adding a reusable view and name it the exact same name as the class it refers to: don't forget to change its class name in the
Identity Inspector
.STEP 3 ⟹ register the .xib file in the controller:
STEP 4 ⟹ support this new cell in your data source (a header is a supplementary element for a collection view):
... and in your delegate (this intializes the header size and makes it appear):
.. after adding a global
var headerHeight: CGFloat = 90.0
for initialization.STEP 5 ⟹ create the custom flow layout to adapt the header height to the new font size:
Don't forget to update the storyboard in
STEP 6 ⟹ inform the controller to trigger a layout update when the user changes the font size:
Interface Builder
:Following this rationale, the correct height of the headers is automatically set up according to the headers font size ⟹ I suggest to use the Xcode 11 new feature to test the
Dynamic Type
very quickly.