Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView with autosizing cell (estimatedSize) and sectionHeadersPinToVisibleBounds goes mental

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
}

Animation of result

Details of lagging in video: https://vimeo.com/203284395

like image 737
Pavel Gatilov Avatar asked Jan 27 '17 15:01

Pavel Gatilov


1 Answers

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.

like image 64
Pavel Gatilov Avatar answered Oct 21 '22 05:10

Pavel Gatilov