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

查看:18
本文介绍了在 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/StackOverflow51375566p>

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 idea: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).请参阅 马特答案.

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

这篇关于在 iOS 12 中,UICollectionView 何时布局单元格,在 nib 中使用 autolayout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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