I am trying to show HeaderView in my UICollectionView class and I use UICollectionReusableView class for that.
Actually I am showing HeaderView in my CollectionView but It does not reach to safe area.
I use auto layout programmatically and I wrote extension to do that.
Here is my class and extensions that I use in my code:
import Foundation
import UIKit
private let headerIdentifer = "HeaderCell"
class ProfileController: UICollectionViewController {
//MARK: - Properties
//MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
configureProfileCollectionView()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.isHidden = true
}
//MARK: - Helpers
func configureProfileCollectionView() {
collectionView.backgroundColor = .white
collectionView.register(HeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerIdentifer)
}
}
extension ProfileController {
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerIdentifer, for: indexPath) as! HeaderView
return header
}
}
extension ProfileController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: view.frame.width, height: 300)
}
}
import Foundation
import UIKit
class HeaderView: UICollectionReusableView {
//MARK: - Properties
private lazy var containerView: UIView = {
let view = UIView()
view.backgroundColor = .systemBlue
view.addSubview(backButton)
backButton.anchor(top: view.topAnchor, left: view.leftAnchor,
paddingTop: 42, paddingLeft: 16)
backButton.setDimensions(width: 30, height: 30)
return view
}()
private lazy var backButton: UIButton = {
let button = UIButton(type: .system)
button.setImage(UIImage(named: "baseline_arrow_back_white_24dp")?.withRenderingMode(.alwaysOriginal), for: .normal)
button.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside)
return button
}()
//MARK: - Lifecyle
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(containerView)
containerView.anchor(top: topAnchor, left: leftAnchor, right: rightAnchor, height: 108)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//MARK: - Selectors
@objc func backButtonTapped() {
}
}
import UIKit
extension UIView {
func anchor(top: NSLayoutYAxisAnchor? = nil,
left: NSLayoutXAxisAnchor? = nil,
bottom: NSLayoutYAxisAnchor? = nil,
right: NSLayoutXAxisAnchor? = nil,
paddingTop: CGFloat = 0,
paddingLeft: CGFloat = 0,
paddingBottom: CGFloat = 0,
paddingRight: CGFloat = 0,
width: CGFloat? = nil,
height: CGFloat? = nil) {
translatesAutoresizingMaskIntoConstraints = false
if let top = top {
topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
}
if let left = left {
leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
}
if let right = right {
rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
}
if let width = width {
widthAnchor.constraint(equalToConstant: width).isActive = true
}
if let height = height {
heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
func center(inView view: UIView, yConstant: CGFloat? = 0) {
translatesAutoresizingMaskIntoConstraints = false
centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: yConstant!).isActive = true
}
func centerX(inView view: UIView, topAnchor: NSLayoutYAxisAnchor? = nil, paddingTop: CGFloat? = 0) {
translatesAutoresizingMaskIntoConstraints = false
centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
if let topAnchor = topAnchor {
self.topAnchor.constraint(equalTo: topAnchor, constant: paddingTop!).isActive = true
}
}
func centerY(inView view: UIView, leftAnchor: NSLayoutXAxisAnchor? = nil, paddingLeft: CGFloat? = nil, constant: CGFloat? = 0) {
translatesAutoresizingMaskIntoConstraints = false
centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: constant!).isActive = true
if let leftAnchor = leftAnchor, let padding = paddingLeft {
self.leftAnchor.constraint(equalTo: leftAnchor, constant: padding).isActive = true
}
}
func setDimensions(width: CGFloat, height: CGFloat) {
translatesAutoresizingMaskIntoConstraints = false
widthAnchor.constraint(equalToConstant: width).isActive = true
heightAnchor.constraint(equalToConstant: height).isActive = true
}
func addConstraintsToFillView(_ view: UIView) {
translatesAutoresizingMaskIntoConstraints = false
anchor(top: view.topAnchor, left: view.leftAnchor,
bottom: view.bottomAnchor, right: view.rightAnchor)
}
}
2
Answers
The
UICollectionReusableView
is set up fine I believe and I think an automatic inset is applied to theUICollectionView
because of the safe area.Try one of the two options below in your
viewDidLoad
and it might workMore simple solution. No need to write any code!!!