-->

UICollectionViewFlowLayout大小警告当旋转装置,以景观(UICollecti

2019-08-07 21:43发布

我们使用的是UICollectionView以显示覆盖整个屏幕(减去状态和导航栏)细胞。 单元格大小设置从self.collectionView.bounds.size

- (void)viewWillAppear:(BOOL)animated
{
    //
    // value isn't correct with the top bars until here
    //
    CGSize tmpSize = self.collectionView.bounds.size;
    _currentCellSize = CGSizeMake( (tmpSize.width), (tmpSize.height));
}

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout*)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    return _currentCellSize;
}

这为每个设备的正确尺寸。 每个小区被定义为没有插图,和布局具有没有页眉或页脚。 然而,当我们从旋转纵向到横向,我们得到以下的“投诉”:

the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.

现在我明白了这个错误,但是我们重新设置单元格的大小,并使用内置旋转过渡流布局:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    //self.collectionView.bounds are still the last size...not the new size here
}
- (void)didRotateFromInterfaceOrientation: UIInterfaceOrientation)fromInterfaceOrientation
{
    CGSize tmpSize = self.collectionView.bounds.size;
    _currentCellSize = CGSizeMake( (tmpSize.width), (tmpSize.height));
    [self.collectionView performBatchUpdates:nil completion:nil];//this will force the redraw/size of the cells.
}

细胞在景观正确呈现。

它好像在流式布局看到旧的小区的大小(这会导致投诉,因为这将是太高),但读/渲染设置新的单元尺寸didRotateFromInterfaceOrientation

是否有摆脱投诉的方法吗?

我们试过有没有运气访问到正确的目标屏幕大小(与当前屏幕尺寸)的设备旋转过渡期间找到另一钩。 调试输出显示后的投诉发生willRotateToInterfaceOrientation但在此之前didRotateFromInterfaceOrientation

我们也已经验证了明显; 如果我们设置单元格高度是固定的尺寸小于横向屏幕高度,不会出现投诉。 另外,从横向旋转回纵向时不会发生投诉。

一切都正常运行,并正确呈现。 然而这种抱怨我们担心。 任何人有任何意见或解决方案?

Answer 1:

我得到同样的警告。 不满意的“reloadData”的方法,我发现,调用[self.collectionView.collectionViewFlowLayout invalidateLayout]设置集合视图的帧之前关掉了报警,并取得了预期的结果。



Answer 2:

不要把这个装,但未被接受,芭比的另一个虾。

- (CGSize)collectionView:(UICollectionView *)collectionView 
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    [collectionView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    return CGSizeMake(100, collectionView.frame.size.height);
}

刚刚回国的细胞大小之前设置内容插图奏效了我。

注意:

我正在使用Storyboard的容器以加载一个UIViewController内搜集视图。 我试图在故事板的FlowLayout对象上设置此。 在故事板的集合视图。 并重写UICollectionViewDelegateFlowLayout之一; 虽然我不记得哪一个。 我也不知道这是否会为垂直布局工作。



Answer 3:

[UIViewController willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration]

我叫, [UICollectionViewLayout invalidateLayout]似乎工作不错。



Answer 4:

我解决了它。

你应该让FlowLayout中的高度比collcetionView.frame.size.height少。

 [flowLayout setItemSize:CGSizeMake(width, height)];


 collectionView.frame = CGRectMake(12, 380, 290, 80);


Answer 5:

很多解决方案,建议增加invalidateLayoutwillAnimateRotationToInterfaceOrientation -但由于iOS的8不赞成这种方式。

对于iOS 8及更高版本,使用:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    [self.collectionView.collectionViewLayout invalidateLayout];
}

由于这里@ user7097242的评论是swift4版本:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    self.collectionView.collectionViewLayout.invalidateLayout()
}


Answer 6:

我遇到同样的问题。 如果集合观点显示在纵向的时候,当旋转为横向细胞就会消失。 我没有其他的答案的组合在这里解决这个问题。

我把我的观点以接收(包含UICollectionView一) UIDeviceOrientationDidChangeNotification通知。 在响应该通知,UICollectionView框架调整后的方法,我做了以下内容:

- (void)orientationChanged:(NSNotification *)notification
{
    CGSize size = (CGSize){self.frame.size.width - 2*kContentMargin, self.frame.size.height - 2*kContentMargin};
    [self.collectionView.collectionViewLayout setItemSize:size];

    [self.collectionView.collectionViewLayout invalidateLayout];
    [self.collectionView reloadData];
}

需要注意的是UICollectionView的框架,因为它的resizingMask会在初始化时设定为这个被自动设置在旋转时:

self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;


Answer 7:

正好遇到固定同样的问题。 由于我的解决方案是沿着你问的和不符合任何现有的答案的线条更加,我在这里张贴。

#define NUMBER_OF_CELLS_PER_ROW 1

- (UICollectionViewFlowLayout *)flowLayout {
    return (UICollectionViewFlowLayout *)self.collectionViewLayout;
}

- (CGSize)itemSizeInCurrentOrientation {
    CGFloat windowWidth = self.collectionView.window.bounds.size.width;

    CGFloat width = (windowWidth - (self.flowLayout.minimumInteritemSpacing * (NUMBER_OF_CELLS_PER_ROW - 1)) - self.flowLayout.sectionInset.left - self.flowLayout.sectionInset.right)/NUMBER_OF_CELLS_PER_ROW;

    CGFloat height = 80.0f;

   return CGSizeMake(width, height);
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [self.flowLayout invalidateLayout];
    self.flowLayout.itemSize = [self itemSizeInCurrentOrientation];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    // Now that the rotation is complete, load the cells.
    [self.collectionView reloadData];
}


Answer 8:

这解决了这个问题对我来说:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [self.collectionView.collectionViewLayout invalidateLayout];
}

而我使用的设置大小此委托方法:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath

我可以从那里用这个与旋转后的正确框架:

self.collectionView.frame.size


Answer 9:

我的修复是为取消选中“调整滚动查看插图”在IB视图控制器,因为我需要我的导航栏为半透明一样简单。



Answer 10:

这对我的作品:(并希望它也适用于你!)

- (void)viewWillLayoutSubviews 
{     
     self.flowLayout.itemSize = CGSizeMake(self.collectionView.bounds.size.width/4,self.collectionView.bounds.size.height);    
     [self.flowLayout invalidateLayout];
}

- (void)viewDidLayoutSubviews     
{
    self.flowLayout.itemSize = CGSizeMake(self.collectionView.bounds.size.width/4,self.collectionView.bounds.size.height); 
}


Answer 11:

我面临着同样的问题。 这里是我如何解决它。 希望能帮助到你

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(    NSTimeInterval)duration
{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    [self.collectionView reloadData];
}


Answer 12:

试试这个...

UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;

layout.itemSize = CGSizeMake(0.1, 0.1);

这是为我工作。



Answer 13:

调整一个UICollectionView的框架时,我遇到了同样的问题。 如果我用的FlowLayout委托方法返回小区的大小(这将是基于含UICollectionView的大小来更新),我会得到错误信息,当我调整大小(小)的所述UICollectionView的帧,因为它似乎没有抱怨之前,要求更新的大小信息的委托。 重画它最终会要求委托方法大小的信息,但它仍然会发出在我分配了一个新的帧方法时的警告。 为了摆脱的警告,我明确设置UICollectionViewFlowLayout对象的itemSize属性之前我设定的框架,以一个新的较小值。 我的情况是很简单的,我认为我可以逃脱在这一点上做的itemSize计算(因为我在集合视图中的所有项目都是一样的大小),而不是依赖于委托方法。 只需设置itemSize特性,同时留下实现没有解决问题的委托方法,因为我认为它忽略itemSize的值,如果它检测到的委托方法来实现(如果它知道它的存在,为什么没有把它?!)。 希望这有助于 - 或许你也可以明确地旋转之前设置itemSize。



Answer 14:

只是为了抑制警告和(可能,不知道)在返回前的尺寸提高性能,你可以

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath

检查是否视图控制器是在旋转的过程中,如果它是返回一些相对小的尺寸等CGSizeMake(0.1, 0.1)



Answer 15:

你也可以继承UICollectionView并重写setBounds: 还有之前调用[super setBounds:]项目大小可以调整到新的边界。
您应该检查范围的大小是否已经改变,因为setBounds:被调用也同时滚动。



Answer 16:

下面的代码固定对我来说:

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.collectionView.frame.size;
}


Answer 17:

我用一个UICollectionViewFlowLayoutInvalidationContext ,我在其中计算新的偏移,使得它保持了相同的内容偏移。 我自己的函数collectionViewSizeForOrientation:返回适当的大小。 它并不完美,但至少它不是简略:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    CGSize fromCollectionViewSize = [self collectionViewSizeForOrientation:[self interfaceOrientation]];
    CGSize toCollectionViewSize = [self collectionViewSizeForOrientation:toInterfaceOrientation];

    CGFloat currentPage = [_collectionView contentOffset].x / [_collectionView bounds].size.width;
    NSInteger itemCount = [_collectionView numberOfItemsInSection:0];

    UICollectionViewFlowLayoutInvalidationContext *invalidationContext = [[UICollectionViewFlowLayoutInvalidationContext alloc] init];

    [invalidationContext setContentSizeAdjustment:CGSizeMake(toCollectionViewSize.width * itemCount - fromCollectionViewSize.width * itemCount, toCollectionViewSize.height - fromCollectionViewSize.height)];
    [invalidationContext setContentOffsetAdjustment:CGPointMake(currentPage * toCollectionViewSize.width - [_collectionView contentOffset].x, 0)];

    [[_collectionView collectionViewLayout] invalidateLayoutWithContext:invalidationContext];

    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

collectionViewSizeForOrientation:在我的情况如下,假设插图和项目间距是0:

- (CGSize)collectionViewSizeForOrientation:(UIInterfaceOrientation)orientation
{
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;

    CGFloat width = UIInterfaceOrientationIsLandscape(orientation) ? MAX(screenSize.width, screenSize.height) : MIN(screenSize.width, screenSize.height);
    CGFloat height = UIInterfaceOrientationIsLandscape(orientation) ? MIN(screenSize.width, screenSize.height) : MAX(screenSize.width, screenSize.height);

    return CGSizeMake(width, height);

}



Answer 18:

试图找到一个解决方案,以沉默这些警告在iOS 7被证明对我来说很难。 我最终诉诸继承我的UICollectionView并添加以下代码。

- (void)setFrame:(CGRect)frame
{
    if (!iOS8 && (frame.size.width != self.frame.size.width))
    {
        [self.collectionViewLayout invalidateLayout];
    }

    [super setFrame:frame];
}

有些人可能会希望做一个全尺寸检查与CGSizeEqualToSize()



Answer 19:

尝试didRotateFromInterfaceOrientation的结尾:

[self.collectionView setNeedsLayout]

如果它不工作,尝试将所有这些东西从didRotateFromInterfaceOrientation移动到willRotateToInterfaceOrientation



Answer 20:

注:在我的情况,我发现我们设置preferredContentSize的财产UIViewController问题。 如果你觉得这是你的情况,你可能要处理的以下方法UICollectionViewDelegateFlowLayout协议:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGSize size = collectionViewLayout.collectionView.bounds.size;
    ...
    return size;
}


Answer 21:

我知道这是一个老问题,但我只是得到了同样的问题,花了一个小时来解决这个问题。 我的问题是,它似乎UICollectionView的帧大小永远是错的(高度不匹配的容器),而我设置帧大小权UICollectionView流布局委托调用之前。 所以,我对方法重新设置UICollectionView帧大小:

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath

而这奏效了。 高度现在显示正确的警告了。



文章来源: UICollectionViewFlowLayout Size Warning When Rotating Device to Landscape