How to add HeaderView in UICollectionView like UITableView's tableHeaderView
Solution 1:
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 320, self.view.frame.size.height) collectionViewLayout:flowlayout];
self.collectionView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);
UIImageView *imagev = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"015.png"]];
imagev.frame = CGRectMake(0, -50, 320, 50);
[self.collectionView addSubview: imagev];
[self.view addSubview: _collectionView];
I use the attribute contentInset
to insert a frame to the top of the UICollectionView
, then I add the image view to it, and it succeeds. I think it can act excactly as UITableView
's tableHeaderView
property. What do you think?
Solution 2:
I've put a view at the top of a collection view by just adding a UIView as a subview of the collection view. It does scroll up with the collection view and it has normal UIView user interaction. This works ok if you have no section header, but doesn't work if you do. In that situation, I don't see anything wrong with the way you're doing it. I'm not sure why you're not detecting touches, they work fine for me.
Solution 3:
Since iOS 13 a canonical way to set the header is to use UICollectionViewCompositionalLayoutConfiguration
This way allows setting boundarySupplementaryItems
per section or globally for a collection view.
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44))
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: "header", alignment: .top)
let config = NSCollectionViewCompositionalLayoutConfiguration()
config.boundarySupplementaryItems = [header]
let layout = UICollectionViewCompositionalLayout(sectionProvider: sectionProvider, configuration: config)
return layout
To learn more visit the official documentation at: https://developer.apple.com/documentation/appkit/nscollectionviewcompositionallayoutconfiguration
Solution 4:
I ended up using a UICollectionView extension to add my custom header. Using a specific tag, I'm able to fake the stored property to identify my custom header (all transparent from outside). You might have to scroll to a specific offset if the layout of the UICollectionView is not completed when you add your custom header.
extension UICollectionView {
var currentCustomHeaderView: UIView? {
return self.viewWithTag(CustomCollectionViewHeaderTag)
}
func asssignCustomHeaderView(headerView: UIView, sideMarginInsets: CGFloat = 0) {
guard self.viewWithTag(CustomCollectionViewHeaderTag) == nil else {
return
}
let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
headerView.frame = CGRect(x: sideMarginInsets, y: -height + self.contentInset.top, width: self.frame.width - (2 * sideMarginInsets), height: height)
headerView.tag = CustomCollectionViewHeaderTag
self.addSubview(headerView)
self.contentInset = UIEdgeInsets(top: height, left: self.contentInset.left, bottom: self.contentInset.bottom, right: self.contentInset.right)
}
func removeCustomHeaderView() {
if let customHeaderView = self.viewWithTag(CustomCollectionViewHeaderTag) {
let headerHeight = customHeaderView.frame.height
customHeaderView.removeFromSuperview()
self.contentInset = UIEdgeInsets(top: self.contentInset.top - headerHeight, left: self.contentInset.left, bottom: self.contentInset.bottom, right: self.contentInset.right)
}
}
}
CustomCollectionViewHeaderTag refers to the tag number you give to your header. Make sure it is not the tag of anotherView embedded in your UICollectionView.
Solution 5:
The best way to achieve this is to make a section header for the first section. Then set the UICollectionViewFlowLayout's property:
@property(nonatomic) BOOL sectionHeadersPinToVisibleBounds
or swift
var sectionHeadersPinToVisibleBounds: Bool
to NO (false for swift). This will ensure that the section header scrolls continuously with the cells and does not get pinned to the top like a section header normally would.