Consider the following situation. I have an UICollectionView
(inside UICollectionViewController
), which looks almost the same as UITableView
(the reason why I don't use UITalbeView
is because I have non data views on layout, that I don't want to manage and mess with my IndexPath
).
In order to achieve the autosizing cells I've set estimatedItemSize
, something like that:
layout.estimatedItemSize = CGSize(width: self.view.bounds.size.width, height: 72)
Also, in my cell I have layout attributes:
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
return layoutAttributes
}
So, by doing that I've got exact layout as UITableView
with autosizing. And it works perfectly.
Now, I am trying to add the header and pin it on scrolling to the top of the section, like that:
layout.sectionHeadersPinToVisibleBounds = false
but layout goes into weird state, I have glitches all over the place, cells overlapping each other, and headers sometimes doesn't stick.
UPDATE:
The code of view controller and cell:
class ViewController: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
let layout = collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
layout.sectionHeadersPinToVisibleBounds = true
layout.estimatedItemSize = CGSize(width: collectionView?.bounds.size.width ?? 0, height: 36) // enables dynamic height
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 10
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.heightConstraint.constant = CGFloat(indexPath.row * 10 % 100) + 10 // Random constraint to make dynamic height work
return cell
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
return collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "Header", for: indexPath)
}
class CustomCell : UICollectionViewCell {
let identifier = "CustomCell"
@IBOutlet weak var rectangle: UIView!
@IBOutlet weak var heightConstraint: NSLayoutConstraint!
override func awakeFromNib() {
translatesAutoresizingMaskIntoConstraints = false
}
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
return layoutAttributes
}
Details of lagging in video: https://vimeo.com/203284395
Update from WWDC 2017:
My colleague was on WWDC 2017, and he asked one of the UIKit engineers about this issue. The engineer confirmed that this issue is known bug by Apple and there is no fix at that moment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With