Situlation
I made a horizontal scrolling collection view with UICollectionViewFlowLayout.automaticSize. The collection view has height of 40 The cell has height of 40 which I set by autolayou on init.
Problem
The problem is that ONLY cells displayed on first displaying the collection view has size of 50x50 which overridden autolayout height of 40 I manually set by code.
I checked the size on willDisplayCell delegate method.
When I scroll the collection view to display other cells, each newly displayed cells have proper size with heigh of 40.
Although the cells with 50x50 size(as logged) are being displayed correctly(with height 40 it seems) on the screen.
From this, I get error messaged(logged) when I run the app on simulator and the app crashed on if I run on my real device(iPhone8 iOS 11).
Code
ViewController
import UIKit
class HorizontalTabNavigationViewController: UIViewController {
// MARK: - Collection View
private lazy var navigationCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = .white
cv.dataSource = self
cv.delegate = self
return cv
}()
private typealias Cell = HorizontalTabNavigationCell
private let cellId: String = "cell"
// MARK: - Property
var items: [HorizontalTabNavigationItem] = []
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
self.view.translatesAutoresizingMaskIntoConstraints = false
navigationCollectionView.register(Cell.self, forCellWithReuseIdentifier: cellId)
navigationCollectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
setupSubviews()
}
private func setupSubviews() {
view.addSubview( navigationCollectionView )
[
navigationCollectionView.topAnchor .constraint(equalTo: view.topAnchor),
navigationCollectionView.leftAnchor .constraint(equalTo: view.leftAnchor),
navigationCollectionView.rightAnchor .constraint(equalTo: view.rightAnchor),
navigationCollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
].forEach { $0.isActive = true }
}
}
extension HorizontalTabNavigationViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! Cell
//cell.setProperties(item: items[indexPath.row])
//print("Cell for item: \(items[indexPath.row].title)")
return cell
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
print("Cell Size on willDispaly cell")
print(cell.bounds.size)
print("\n")
}
}
extension HorizontalTabNavigationViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 5 // Defines horizontal spacing between cells
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .zero
}
}
Cell
class HorizontalTabNavigationCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupSelfHeight()
self.backgroundColor = .orange
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupSelfHeight() {
self.heightAnchor.constraint(equalToConstant: 40).isActive = true
self.widthAnchor.constraint(equalToConstant: 120).isActive = true
}
}
I solved the problem by setting custom size to flowlayout.
Inspired by Manav's anwer on this question below.
the behavior of the UICollectionViewFlowLayout is not defined, because the cell width is greater than collectionView width