hide header while collection view is loading
You are probably performing some asynchronous operation while the indicator is animating so you should let the collection view know that the operation is finished by calling reloadData
so it'll re-layout its UI elements including the headers via viewForSupplementaryElementOfKind
:
First off, what you need is to return CGSize.zero
from collectionView:layout:referenceSizeForHeaderInSection
if indicator is on screen so the header won't be populated:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if indicatorView.isAnimating {
return CGSize.zero
} else {
return CGSize(width: collectionView.frame.width, height: 50)
}
}
Then wherever you hide the activity indicator (probably in the completion block of the asynchronous operation), you should call collectionView.reloadData
so viewForSupplementaryElementOfKind
will be called again:
// operation is done, refreshing the content..
self.stopActivityIndicatorView()
self.collectionView.reloadData()
...
How can I make a collectionView header become hidden when a button is tapped?
As @SPatel mentioned, set the size to zero.
Then set up a delegate method from the cell to the VC so that the VC knows to invalidate layouts.
For instance:
Cell Class
protocol HideHeaderViewDelegate {
func hideHeaderView(hide: Bool)
}
class HeaderView: UICollectionReusableView {
var delegate: HideHeaderViewDelegate?
@IBOutlet weak var hideButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
@IBAction func hideButtonAction(_ sender: Any) {
self.frame.size = CGSize.zero
guard let delegate = delegate else { return }
delegate.hideHeaderView(hide: true)
}
}
View Controller
extension ViewController: HideHeaderView {
func hideHeaderView(hide: Bool) {
if hide == true {
print(hide)
// invalidate your layout here
}
}
}
Don't forget to set the delegate
func collectionView(_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String,
at indexPath: IndexPath) -> UICollectionReusableView {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader,
withReuseIdentifier: "headerView", for: indexPath) as! HeaderView
headerView.delegate = self
return headerView
}
Removing collection view header if collection view is empty
I think you can achieve that like this:
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if collectionView.numberOfItems(inSection: section) == 0 {
return CGSize.zero
} else {
let headerView = self.view.subviews[0].subviews[0] as! UICollectionReusableView
let existingSize = headerView.frame.size
return existingSize
}
}
}
UICollectionViewCells hiding behind headerView
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionView.elementKindSectionHeader:
/// PROBLEM
reusableview.frame = CGRect(x: 0 , y: 0, width: self.view.frame.width, height: 40)
return reusableview
default: fatalError("Unexpected element kind")
}
}
You are not supposed to set the frame of UICollectionView.elementKindSectionHeader
. UICollectionView
does all of that for you. You just need to tell it how big (CGSize
) it needs to be.
You can tell UICollectionView
about this size via following method -
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: collectionView.bounds.width, height: 40)
}
}
How can I enable/disable section headers in UICollectionView programmatically?
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.
Related Topics
How to Condense Unwrapping Multiple Optionals in Swift
Why Is Swift Counting This Grapheme Cluster as Two Characters Instead of One
Enum Named 'Type' in Nested Class Fails
How to Change Orientation for Avcapturemoviefileoutput in Swift
Why Is My Libraries Not Able to Expand on The Cocoapods and Shows as Objective-C Not Swift
Arkit - Raycasting Using a World Ray Instead of a Screen Point
Get Output Frames Failed, State 8196
Show and Hide Window Instead of Terminating App on Close Click in Cocoa App
What Does an Underscore "_" Mean in Swift
Navigationlink Inside .Searchable Does Not Work
Swift: Urlsession.Shared.Datatask Says Status Code 304 = 200
Combined Watch Os and iOS Framework
"Ambiguous Reference to Member Map" When Attempting to Append/Replace Array Element