UICollectionView旋转后屏幕尺寸不正确



我有一个UICollectionView在我的视图控制器定义如下:

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = Constants.minimumLineSpacing
layout.minimumInteritemSpacing = Constants.minimumInteritemSpacing
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = Constants.backgroundColor
collectionView.contentInset = Constants.collectionViewContentInsets
collectionView.refreshControl = refreshControl

我在sizeForItemAt中设置了单元格大小:

func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath
) -> CGSize {
let collectionViewHorizontalInset = Constants.collectionViewInsets.left + Constants.collectionViewInsets.right
let cellWidth = isPortrait
? (screenSize.width - collectionViewHorizontalInset - Constants.minimumInteritemSpacing) / 2.0
: (screenSize.width - collectionViewHorizontalInset - Constants.minimumInteritemSpacing * 2.0) / 3.0
return CGSize(width: cellWidth, height: Constants.cellHeight)
}

与scensize的关系如下:

private var screenSize: CGSize {
view.bounds.size
}

属性isPortrait跟踪方向,在viewDidLoad中:

isPortrait = view.bounds.size.width < view.bounds.size.height

viewWillTransition中我有以下内容:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
isPortrait = size.width < size.height
collectionView.collectionViewLayout.invalidateLayout()
}

当我旋转设备时,似乎它正在获得不正确的屏幕尺寸,因此计算单元格的不正确宽度。例如,如果我在横向加载应用程序,将有每行3单元格这是正确的。然而,如果我然后旋转到纵向和横向,每一行将有4个单元格,这是不正确的。

我在这里做错了什么?旋转后我怎样才能得到正确的屏幕尺寸?

用对我有用的方法回答我自己的问题:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate { _ in
self.collectionView.collectionViewLayout.invalidateLayout()
}
}

似乎关键是使用coordinator.animate,这样当sizeForItemAt进行计算时,屏幕大小将是正确的。

这对我解决你的问题很有帮助。详细信息在注释中添加。

class CollectionViewFlowLayout: UICollectionViewFlowLayout{

/// The default implementation of this method returns false.
/// Subclasses can override it and return an appropriate value
/// based on whether changes in the bounds of the collection
/// view require changes to the layout of cells and supplementary views.
/// If the bounds of the collection view change and this method returns true,
/// the collection view invalidates the layout by calling the invalidateLayout(with:) method.
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {

return (self.collectionView?.bounds ?? newBounds) != newBounds
}
}

最新更新