在iOS 12中,UICollectionView什么时候布局单元格,在nib中使用autolayout [英] In iOS 12, when does the UICollectionView layout cells, use autolayout in nib
问题描述
类似这样的代码
collectionLayout.estimatedItemSize = CGSize(width: 50, height: 25)
collectionLayout.itemSize = UICollectionViewFlowLayoutAutomaticSize
collectionLayout.minimumInteritemSpacing = 10
for _ in 0 ..< 1000 {
let length = Int(arc4random() % 8)
let string = randomKeyByBitLength(length)
array.append(string!)
}
collectionView.reloadData()
单元格约束:
当我在 iOS 12 上运行它时,情况就不一样了.左侧模拟器是 iOS 11,右侧是 iOS 12:
when I run it on iOS 12, it's different. left simulator is iOS 11, and right is iOS 12:
但是,当我滚动它时,单元格的框架会正常.
But, when I scroll it, cells's frames will be normal.
重现问题的示例项目:https://github.com/Coeur/StackOverflow51375566>
Sample project to reproduce the issue: https://github.com/Coeur/StackOverflow51375566
推荐答案
对于所有解决方案,注意不需要在 viewDidLoad
中显式调用 reloadData
:它会自动发生.
For all solutions, note that there is no need to explicitly call reloadData
in viewDidLoad
: it will happen automatically.
灵感来自 Samantha 的想法:invalidateLayout
在 viewDidLoad
中异步.
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()
}
}
解决方案 2
(不完美,见DHennessy13改进)
基于 Peter Lapisu 的回答.viewWillLayoutSubviews
中的 invalidateLayout
.
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
}
正如 DHennessy13 所指出的,当前的 viewWillLayoutSubviews
解决方案并不完美,因为它在旋转屏幕时会使布局失效.
As noted by DHennessy13, this current solution with viewWillLayoutSubviews
is imperfect as it will invalidateLayout when rotating the screen.
您可以关注关于此解决方案的DHennessy13改进.
You may follow DHennessy13 improvement regarding this solution.
基于 Tyler Sheaffer 回答 的组合,Shawn Aukstak 移植到 Swift 和 Samantha 的想法.子类化您的 CollectionView 以在 layoutSubviews
上执行 invalidateLayout
.
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()
}
}
这个解决方案很优雅,因为它不需要更改您的 ViewController 代码.我已经在这个示例项目的分支 AutoLayoutCollectionView 上实现了它 https://github.com/Coeur/StackOverflow51375566/tree/AutoLayoutCollectionView.
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.
重写 UICollectionViewCell 默认约束.请参阅拉里回答.
Rewrite UICollectionViewCell default constraints. See Larry answer.
实现collectionView(_:layout:sizeForItemAt:)
并返回cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
.请参阅无题答案.
这篇关于在iOS 12中,UICollectionView什么时候布局单元格,在nib中使用autolayout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!