如何在方向更改

时间:2017-03-16 05:58:10

标签: ios swift uicollectionview uikit

我有一个带有自定义UICOllectionViewLayout的UICollectionViewSubclass

我如何最好地处理方向更改的itemSize更改?

class CollectSubclass: UICollectionView {

    /// When orientation changes, then invalidate the layout
    open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if ((traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass) || (traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass)) {
            collectionViewLayout.invalidateLayout()   
        }
    }
}

一旦布局在方向更改时失效, 我计算单元格的size.width到UICollectionView的width

这适用于iPhone 7 Plus模拟器,但在较小的模拟器上失败,如iPhone 7,5,SE等。

似乎一旦invalidateLayout被调用,就会触发以下函数

 /// Lays out subviews.
override open func layoutSubviews() {
    super.layoutSubviews()
}

这个函数依次调用prepare子类上的UICollectionViewLayout函数,我使用collectionView的新框架来计算单元格的大小。

在iPhone-7-Plus上,traitCollectionDidChange会被触发一次。一旦触发layoutSubviews,就会触发prepare

但是,在较小的模拟器上,traitCollectionDidChange会被触发一次,但layoutSubviews会被触发两次。

使用layoutSubviews的第一个触发器,UICOllectionView帧大小几乎它应该是什么。在第二个触发器上,UICOllectionView帧大小现在应该是正确的大小。

使用两种不同的帧尺寸调用两次将使我准备两次布局(非常昂贵)。

我是否遗漏了UICOllectionViews和UICollectionViewLayouts的子类?任何帮助表示赞赏。

我还可以根据需要提供示例项目

1 个答案:

答案 0 :(得分:1)

如果在您的设置中,UICollectionViewCells之一的宽度仅基于UICollectionView的大小以及屏幕的大小和方向(并且没有其他因素),则以下是一种设置集合视图单元大小的简洁方法:

1)当视图首次加载时,预先计算单元格在纵向和横向中的大小。还要创建一个变量currCellDimensions来保存单元格的当前尺寸,并设置其初始值。

2)沿着以下几行覆盖函数viewWillTransitionToSize:

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    setCurrentCollectionCellDimensions(size)  // This code executes before the rotation begins, but "size" is the size that the main view is going to be after the rotation occurs. As of iOS 8, the size of an object swaps its width and its height when the UI changes its orientation.
    }

3)实现setCurrentCollectionCellDimensions():

    func setCurrentCollectionCellDimensions(newSize: CGSize) {

    if (newSize.width < newSize.height) {
        // set currCellDimensions to what it should be in portrait orientation
    } else {
        // set currCellDimension to what it should be in landscape orientation
    }

    if collectionView != nil {

        collectionView.collectionViewLayout.invalidateLayout() // To trigger sizeForItemAtIndexPath to recalculate cell sizes

    collectionView.reloadData() // To trigger cellForItemAtIndexPath to redraw the cells that are visible to the user.  Without this call, the cell layout looks wrong on some iPhones.
    }
}

4)最后,让sizeForItemAtIndexPath()返回currCellDimensions