How can I enable/disable section headers in UICollectionView programmatically?
It can be easily done easily done in Storyboard (checkbox), but how about doing it in code?
How can I enable/disable section headers in UICollectionView programmatically?
It can be easily done easily done in Storyboard (checkbox), but how about doing it in code?
You can either use the collectionView:layout:referenceSizeForHeaderInSection:
method of the UICollectionViewDelegateFlowLayout
and return CGSizeMake(0,0)
or set accordingly the headerReferenceSize
of UICollectionViewFlowLayout
.
Edit:
headerReferenceSize
is actually the property that storyboard uses to show/hide the headers. I've added the relevant lines from the Storyboard file
With section checkbox on:
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="xAt-Uo-bMl">
<size key="headerReferenceSize" width="50" height="50"/></collectionViewFlowLayout>
With section checkbox off
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="xAt-Uo-bMl">
<size key="headerReferenceSize" width="0" height="0"/></collectionViewFlowLayout>
Edit #2:
From the official docs:
Each section in a flow layout can have its own custom header and footer. To configure the header or footer for a view, you must configure the size of the header or footer to be non zero. You can do this by implementing the appropriate delegate methods or by assigning appropriate values to the headerReferenceSize and footerReferenceSize properties. If the header or footer size is 0, the corresponding view is not added to the collection view.
Just change the height to 0 of the headers you don't want to show...
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
if (section == 0) {
return CGSizeZero;
}else {
return CGSizeMake(collectionView.frame.size.width,50);
}
}
Neither nil nor [UIView new] works an both throw the same error. The best answer is in How to change the UICollectionView footerview's height programatically
All answers I've found on this subject assume that you're using either UICollectionViewFlowLayout
or its subclass in which you modify supplementary view's size directly.
I think all of those answers have downsides, especially the ones suggesting modifying header size in layout subclass which creates unnecessary coupling of whatever object manages your data and the layout itself. Also, you have to be careful about your header's constraints, otherwise you'll get bombarded with log messages about breaking constraints if you set the view's size to zero.
Just return a valid, empty view.
Create a subclass of UICollectionReusableView
class EmptyCollectionReusableView: UICollectionReusableView {
override func sizeThatFits(_ size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
size.height = .leastNonzeroMagnitude
return size
}
}
register it in your collection view, just like you would with normal supplementary views
let identifier = "emptySupplementaryViewIdentifier"
collectionView.register(EmptyCollectionReusableView.self,
forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: identifier)
and whenever you want to "hide" header you dequeue it, again just like you would with normal supplementary views:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if shouldHideHeader {
return collectionView.dequeueReusableSupplementaryView(ofKind: kind,
withReuseIdentifier: "emptySupplementaryViewIdentifier",
for: indexPath)
}
// Return your normal header
}
When using Diffable data source, insert this code to the supplementaryViewProvider
of your Data Source object
When you simply don't want an header to appear, in the delegate's
viewForSupplementaryElementOfKind
Just return [UIView new];
when kind == UICollectionElementKindSectionHeader:
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
if (kind == UICollectionElementKindSectionHeader) {
return [UIView new]; // Or even nil, I think it would work.
}
...
return /*something else that you want to return*/ ;
}