Uicollectionviewflowlayout Estimateditemsize Does Not Work Properly with iOS12 Though It Works Fine with iOS 11.*

In iOS 12, when does the UICollectionView layout cells, use autolayout in nib

For all solutions, note that there is no need to explicitly call reloadData in viewDidLoad: it will happen automatically.

Solution 1

Inspired by Samantha idea: invalidateLayout asynchronously in viewDidLoad.

override func viewDidLoad() {
super.viewDidLoad()

//[...]

for _ in 0 ..< 1000 {
array.append(randomKeyByBitLength(Int(arc4random_uniform(8)))!)
}

DispatchQueue.main.async {
self.collectionView.collectionViewLayout.invalidateLayout()
}
}

Solution 2

(imperfect, see DHennessy13 improvement on it)

Based on Peter Lapisu answer. invalidateLayout in viewWillLayoutSubviews.

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
}

As noted by DHennessy13, this current solution with viewWillLayoutSubviews is imperfect as it will invalidateLayout when rotating the screen.

You may follow DHennessy13 improvement regarding this solution.

Solution 3

Based on a combination of Tyler Sheaffer answer, Shawn Aukstak port to Swift and Samantha idea. Subclass your CollectionView to perform invalidateLayout on layoutSubviews.

class AutoLayoutCollectionView: UICollectionView {

private var shouldInvalidateLayout = false

override func layoutSubviews() {
super.layoutSubviews()
if shouldInvalidateLayout {
collectionViewLayout.invalidateLayout()
shouldInvalidateLayout = false
}
}

override func reloadData() {
shouldInvalidateLayout = true
super.reloadData()
}
}

This solution is elegant as it doesn't require to change your ViewController code. I've implemented it on branch AutoLayoutCollectionView of this sample project https://github.com/Coeur/StackOverflow51375566/tree/AutoLayoutCollectionView.

Solution 4

Rewrite UICollectionViewCell default constraints. See Larry answer.

Solution 5

Implement collectionView(_:layout:sizeForItemAt:) and return cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize). See matt answer.

In iOS 12, when UICollectionView is created using Self Sizing cells with constraints, upon reload layout has wrong height until I scroll

I think the issue is coming from you calling:

flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

in your project.

If you reset this to something like:

layoutFlow.estimatedItemSize = CGSize(width: UIScreen.main.bounds.size.width, height: 100)

Then it immediately runs smoother.

Note: It is worth noting that the estimated height you set your cells to matters. If you set it to 0 then reloadData() will scroll the collectionView to the top. Setting an accurate value seems to work best in testing

There are still a few bugs which seem to be fixed by removing the

collectionView.collectionViewLayout.invalidateLayout()

and swapping it for something like

collectionView.reloadData()
collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems)

I don't know the specific use that you are wanting this for so I can't fully test how it should be but invalidateLayout seems like the wrong way to reload the collectionView.



Related Topics



Leave a reply



Submit