我实现了一个集合视图,其项目的大小基于集合视图的边界。因此,当大小改变时,例如,由于旋转设备,我需要使布局无效,以便调整单元格的大小以考虑新的集合视图边界。我是通过viewWillTransitionToSize
API完成此操作的。
这很有效,直到用户在包含集合视图的视图控制器上呈现模态视图控制器,旋转设备,然后解除它。发生这种情况时,项目大小未更新为适当的大小。调用viewWillTransitionToSize
并按预期使布局无效,但集合视图的边界仍然是旧值。例如,当从纵向旋转到横向时,集合视图边界值的高度仍然大于宽度。我不确定为什么会这样,但我想知道这是否是改变尺寸无效的最佳方法?有没有更好的方法呢?
我还尝试了对UICollectionViewFlowLayout
进行子类化并覆盖shouldInvalidateLayoutForBoundsChange
以返回YES
,但由于某些原因,即使没有模态演示也无法轮换。它也没有使用正确的集合视图边界。
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(nonnull id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self.collectionView.collectionViewLayout invalidateLayout];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> __nonnull context) {
[self.collectionView.collectionViewLayout invalidateLayout];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> __nonnull context) {
//finished
}];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
//collectionView.bounds.size is not always correct here after invalidating layout as explained above
}
我也尝试在完成块中使用它,但它仍然没有使用正确的集合视图边界。
如果我在viewWillAppear
中再次使布局无效,则会使用正确的集合视图边界来解决问题,并使用模态显示的视图控制器进行旋转。但这不应该是必要的,也许还有其他情况下,它不能正确调整大小。
答案 0 :(得分:20)
我知道问题是什么。当您在invalidateLayout
内调用animateAlongsideTransition
时(在动画块或完成块中),如果在全屏幕上显示模态视图控制器,它实际上不会重新计算布局(但它如果它超过当前的背景,那就会发生。但是如果你像我一样在动画块之外使它无效,它将使它无效。然而,那时集合视图没有为新的大小布局,这解释了为什么我看到它的边界的旧值。此行为的原因是invalidateLayout
不会立即导致重新计算布局 - 它计划在下一个布局过程中发生。当全屏显示模态呈现的视图控制器时,不会发生此布局过程。要强制执行布局,只需在[self.collectionView layoutIfNeeded];
之后立即调用[self.collectionView.collectionViewLayout invalidateLayout];
,仍然在animateAlongsideTransition
块内。这将导致按预期重新计算布局。