集合视图不会在旋转时更新布局

Posted

技术标签:

【中文标题】集合视图不会在旋转时更新布局【英文标题】:Collection View does not update layout at Rotation 【发布时间】:2015-06-26 04:29:47 【问题描述】:

这是应用处于纵向模式时的视图。

当它旋转到横向模式时,它看起来像这样

视图调试器显示UIWindow 没有旋转,如此处所示

UICollectionViewController 是通过 StoryBoard 创建的。我已经尝试对实现shouldInvalidateLayoutForBoundsChangeUICollectionViewFlowLayout 进行子类化,但这并不能解决我的问题。

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds 
    CGRect oldBounds = self.collectionView.bounds;
    if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds)) 
        return YES;
    
    return NO;

请提供下一步要检查什么的想法或请求额外的代码进行调试。

编辑 - 正如 MirekE 所建议的,我尝试向 CollectionView 添加约束,但未能成功。对于CollectionView,Editor->Pin 的所有选项均不可用。

编辑,回复 Andrea -

我的目标是 ios8.3。我的理解是,在轮换时调用的主要方法是viewWillTransitionToSize:withTransitionCoordinator:,它来自UIContentContainerprotocol。我已将以下内容添加到我的 CollectionViewController,但同样的问题仍然存在

-(void)viewWillTransitionToSize:(CGSize)size
      withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator 
    [self.collectionView.collectionViewLayout invalidateLayout];
    [self.collectionView reloadData];

【问题讨论】:

看起来你已经为每个单元格设置了特定的约束,有必要吗? Vinay - 是的,单元格内的标签有 topMargincenterX 约束,但单元格本身没有约束。 根据文档,我认为您应该在某个时候调用viewWillTransitionToSize 中的超级实现。 【参考方案1】:

我不知道您的目标是哪个 iOS 版本,但让我假设您知道旋转过程和在视图控制器中调用的方法。 在其中一种方法中,您只需要调用:

[self.collectionView.collectionViewLayout invalidateLayout];

也许取决于你的布局-reloadData 无需子类化。

编辑 我使用这种方法,我想这不起作用,因为您应该在调整大小后重新布局集合:

- (void) willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator 
    [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];


    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) 
        [self.collectionView.collectionViewLayout invalidateLayout];            
     completion:^(id<UIViewControllerTransitionCoordinatorContext> context) 
        [self.collectionView reloadData];
    ];


我正在做的是将布局失效过程附加到动画过程中。

【讨论】:

我已经更新了问题并回复了您的回答。【参考方案2】:

如果您有 UICollectionViewLayout 的自定义实现,请尝试覆盖方法:

override public func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool 
    let bounds = self.collectionView!.bounds;
    return ((CGRectGetWidth(newBounds) != CGRectGetWidth(bounds) ||
        (CGRectGetHeight(newBounds) != CGRectGetHeight(bounds))));


override public func invalidateLayout() 
    cache.removeAll()  // remove layout attributes ans settings if they exist
    super.invalidateLayout()


干杯!

【讨论】:

【参考方案3】:

看起来你只是在画布上拖动集合视图,但没有添加任何约束。因此,当您旋转设备时,尺寸不会改变。

在故事板中选择集合视图,然后单击 Xcode 底部的 Pin 图标并为顶部、左侧、底部和右侧边距添加约束。完成此操作后,集合视图应在旋转时调整大小。

【讨论】:

当我将集合视图控制器拖到画布上时,集合视图是自动添加的。我用屏幕截图更新了问题,以显示当我尝试固定 Collection View 时会发生什么。没有可用于添加约束的选项。你能详细说明你的答案吗? 我的建议是将集合视图拖到现有控制器。如果这是 CollectionViewController,你不需要做任何事情。当我在我创建的一个小项目中旋转模拟器时,它正确地填充了空间,以便立即对其进行测试。也许您添加了一些覆盖默认值的自定义代码?您是否尝试注释掉您的自定义设置?【参考方案4】:

问题是collectionView 插座没有正确设置。设置collectionView后,一切正常。

collectionView 出口未设置:

collectionView插座组:

【讨论】:

以上是关于集合视图不会在旋转时更新布局的主要内容,如果未能解决你的问题,请参考以下文章

集合视图自动布局

TableView 仅在屏幕旋转后更新

如何使用自动布局以编程方式快速设置旋转时 UICollectionView 的宽度

UIStackView 隐藏视图和旋转时无法满足的布局

滚动圆形布局集合视图

集合视图的自定义布局不更新