在iOS 8中嵌套UICollectionViews,AutoLayout和旋转
我开始使用AutoLayout进行大型项目,并对此感到惊喜。 但是,现在我不得不调整项目来适应轮换和大小类,并且我有很大的麻烦让观点行为正确。
基本的问题是,我有UICollectionViews
的细胞,再次包含UICollectionViews 。 当设备旋转时,基本集合视图将其单元格调整为正确,但嵌套的集合视图中的所有单元格都不会自动调整为新的大小。
经过调查后归结为:
- 当调用
viewWillTransitionToSize
,基础集合视图还没有旋转(如预期的那样) - 在调用viewDidLayoutSubviews之后的一段时间,基础集合视图现在具有旋转的大小 – 但不幸的是,它的单元格还没有 – 它们仍然具有旋转之前的宽度
- 即使在
coordinator animateAlongsideTransition ... completion:{}
blockviewWillTransitionToSize
单元格还没有新的宽度。
上面的意思是没有地方可以告诉嵌套集合视图的单元格来改变它们的大小,因为我还不知道新的宽度。 自动布局系统不会自动调整它们。
其他人是否有同样的问题或知道解决scheme?
在这里回答我自己的问题 – 我终于find了解决办法。 对于任何其他有这个麻烦的人来说,我是这样做的:
主要部分在于将invalidateLayout
和reloadData
调用放在正确的位置:
- 在
willTransitionToSize
函数的基础collectionView的布局上放置一个invalidateLayout
。 - 将一个
reloadData
放在基础collectionView中的coordinator animateAlongsideTransition:
的完成块的willTransitionToSize
函数中调用。 - 确保单元格中任何视图的自动布局约束都设置正确 – 我将单元格视图和自动布局约束连接到单元格的代码中的内容视图。
- 如果您覆盖了集合视图布局的
prepareLayout
函数,请确保预先计算的单元格大小使用正确的宽度,我在这里使用了一个错误的宽度,这导致了一些额外的问题。
感谢TheEye。 我想添加这个作为他们的回应评论,但显然我没有足够的噶(尚),所以认为这是一个附录。
我遇到了同样的问题,但是我的uicollectionview中的单元格在select时有一个“扩展状态”。 如果用户旋转设备,我们调用[self.collectionview reloadData]
,任何展开的单元格都将失去其状态。 您可以select调用performBatchUpdates
并强制集合视图进行布局,而不会丢失任何单元格的状态
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{ [self.collectionView.collectionViewLayout invalidateLayout]; [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { //[self.collectionView reloadData];//this works but reloading the view collapses any expanded cells. [self.collectionView performBatchUpdates:nil completion:nil]; }]; }
TheKey的回答是正确的。 但是,不要重新加载数据,你可以打电话
UICollectionView.collectionViewLayout:finalizeCollectionViewUpdates()
例:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { self.collectionView.collectionViewLayout.invalidateLayout() self.collectionView.collectionViewLayout.finalizeCollectionViewUpdates() }
希望提供一个替代解决scheme。 我不喜欢在协调器的animation完成中调用reloadData或performBatchUpdates的轻微延迟。 两者都导致了AutoLayout警告。
在viewWillTransitionToSize中,在所有可见的嵌套集合视图上调用invalidateLayout,最后在外层/顶层集合视图上调用invalidateLayout。
我的集合视图单元格有一个子集合视图:
class NestableCollectionViewCell: UICollectionViewCell { @IBOutlet weak var collectionView: NestableCollectionView? }
扩展UICollectionView以使嵌套的集合视图无效:
class NestableCollectionView: UICollectionView { func invalidateNestedCollectionViews(){ let visibleCellIndexPaths = self.indexPathsForVisibleItems() for cellIndex in visibleCellIndexPaths { if let nestedCell = self.cellForItemAtIndexPath(cellIndex) as? NestableCollectionViewCell { // invalidate any child collection views nestedCell.collectionView?.invalidateNestedCollectionViews() // finally, invalidate the cell's own collection view nestedCell.collectionView?.collectionViewLayout.invalidateLayout() } } } }
并且,在willTransitionToSize上无效:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) self.collectionView.invalidateNestedCollectionViews() self.collectionView.collectionViewLayout.invalidateLayout() }