我有一个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
}
}