更改流布局的itemSize后,单元格大小不会更新

时间:2017-07-29 16:40:00

标签: ios uicollectionview uicollectionviewcell uicollectionviewlayout

在我的应用程序中,我有一个全屏分页集合视图,每个单元格也需要全屏,因此集合视图布局的项目大小需要与视图控制器视图的边界大小相同。要做到这一点,在viewDidLayoutSubviews我只是设置项目大小,它按预期工作。当我显示此屏幕时,viewDidLayoutSubviews被调用3次,每次iPhone 7的视图边界大小为375.0 x 667.0。单元格的大小与预期的大小相同。

但是当使用3D Touch peek和pop来呈现此屏幕时,单元格的大小不是预期的,无论是偷看还是弹出。 viewDidLayoutSubviews被调用4次,具有这些边界大小:

--- peek triggered ---
375.0 x 569.524495677234
375.0 x 569.524495677234
375.0 x 720.821325648415
--- pop triggered ---
375.0 x 667.0

当偷看时,集合视图为“全屏”,高度为721,单元格的预期宽度为375,但单元格高度为569,应该是721.弹出时,集合视图视图高度按预期更改为667,但单元格高度仍为569。

我在设置collectionView.layoutIfNeeded()后尝试调用itemSize,但结果是一样的。为什么集合视图不会更新单元格大小?

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    print("\(view.bounds.width) x \(view.bounds.height)")

    let boundsSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height))
    let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

    if flowLayout.itemSize != boundsSize {
        flowLayout.itemSize = boundsSize

        collectionView.layoutIfNeeded() //this doens't help
    }
}

5 个答案:

答案 0 :(得分:8)

将检查器的集合视图的“估计大小”更改为“无”! 以上答案对我都不起作用。

Estimate Size

答案 1 :(得分:3)

似乎是UICollectionViewFlowLayout的错误, 我必须在invalidateLayout()之前调用prepare()

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()


    guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else
    {
        return
    }

    layout.itemSize = cellSize
    layout.minimumLineSpacing = space
    layout.prepare()  // <-- call prepare before invalidateLayout
    layout.invalidateLayout()
}

答案 2 :(得分:0)

尝试将collectionView.layoutIfNeeded()替换为flowLayout.invalidateLayout()

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    print("\(view.bounds.width) x \(view.bounds.height)")

    let boundsSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height))
    let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

    if flowLayout.itemSize != boundsSize {
        flowLayout.itemSize = boundsSize

        debugPrint("Called")
        flowLayout.invalidateLayout()
    }
}

答案 3 :(得分:0)

您可以将collectionView(_:layout:sizeForItemAt:)viewDidLayoutSubviews一起使用。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    print("\(view.bounds.width) x \(view.bounds.height)")

    let boundsSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height))

    if !boundsSize.equalTo(self. collectionViewItemSize) {
        collectionView.invalidateLayout()
    }
}

var collectionViewItemSize:CGSize = .zero

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {
    self.collectionViewItemSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height));
    return self.collectiViewItemSize;
}

答案 4 :(得分:0)

我最终更改了itemSize中的viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)并将大小传递给了一个方法,该方法将根据视图的未来大小进行数学运算。