在iOS 12中,UICollectionView什么时候布局单元格,在nib中使用autolayout [英] In iOS 12, when does the UICollectionView layout cells, use autolayout in nib

查看:26
本文介绍了在iOS 12中,UICollectionView什么时候布局单元格,在nib中使用autolayout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类似这样的代码

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 的想法:invalidateLayoutviewDidLoad 中异步.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆