我有一个UICollectionViewController,它有一堆单元格,每个单元格都有屏幕大小。
如果我以纵向或横向方式启动应用程序,一切都会按预期工作。
问题是当我更改屏幕方向时,我调用collectionViewLayout.invalidateLayout()
单元格大小保持原样,不调整大小。
我不知道为什么会这样。
这里有一些代码:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
print("size for item")
return CGSize(width: view.frame.width, height: view.frame.height)
}
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: { (_) in
self.collectionViewLayout.invalidateLayout() // layout update
}, completion: nil)
}
在第一次加载时,我从尺寸设置中获取打印件,但在更改方向后,它没有调用它,因此当我更改方向时,单元格尺寸不适合屏幕,因为它适合在发布会上。
任何想法可能导致这个或我在这里做错了什么?
谢谢
修改
不知何故,我试图在willTransition
函数中插入一个print语句,我注意到它并没有触发屏幕旋转。我认为问题出在那里而不是invaldateLayout()
,因为它永远不会触发。
如何不自动调用覆盖功能?
答案 0 :(得分:2)
我可以推荐的是覆盖布局类并实现shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool
class CollectionViewLayoutSelfSizingCells : UICollectionViewFlowLayout
{
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
if let collectionView = self.collectionView {
return collectionView.frame.size != newBounds.size
}
return false
}
}
这是我发现的最好的解决方案,它适用于整个项目。
说实话,我很惊讶UICollectionViewFlowLayout
答案 1 :(得分:2)
您应该实施func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
方法。只要视图控制器的大小发生变化(例如,纵向和横向旋转时),就会调用此方法:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (_) in
self.collectionViewLayout.invalidateLayout() // layout update
}, completion: nil)
}
答案 2 :(得分:2)
UICollectionViewFlowLayoutInvalidationContext
上有一个专用标志,称为invalidateFlowLayoutDelegateMetrics
。文档内容如下:
此属性的默认值为false。如果由于任何项目大小的更改而使布局无效,则将此属性设置为true。 如果将此属性设置为true,则流布局对象将重新计算其项目和视图的大小,并根据需要查询该信息的委托对象。
在流layotu子类中提高标志。
class CollectionViewFlowLayout: UICollectionViewFlowLayout {
override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext {
let context = super.invalidationContext(forBoundsChange: newBounds) as! UICollectionViewFlowLayoutInvalidationContext
if let collectionView = collectionView {
context.invalidateFlowLayoutDelegateMetrics = collectionView.bounds.size != newBounds.size
}
return context
}
}