UICollectionViewFlowLayout Size Warning When Rotat

2020-05-17 00:20发布

We are using a UICollectionView to display cell that cover the full screen (minus the status and nav bar). The cell size is set from 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;
}

This sets the correct sizing for each device. Each cell is defined to have no insets, and the layout has no header or footer. However, when we rotate from portrait to landscape we get the following "complaint":

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.

Now I understand this error, however we reset the size of the cell and use the flow layouts built in rotation transition:

-(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.
}

The cells render correctly in landscape.

It seems as though the Flow Layout sees the old cell size (which causes the complaint since it will be too tall), but does read/render the new cell size set in didRotateFromInterfaceOrientation.

Is there a way to get rid of the complaint?

We've tried finding another hook during a device rotate transition that has access to the correct target screen size (vs the current screen size) with no luck. Debug output shows the complaint happens after willRotateToInterfaceOrientation but before didRotateFromInterfaceOrientation.

We've also verified the obvious; if we set up the cell height to be a fixed size less than the landscape screen height, the complaint doesn't occur. Also, the complaint does not occur when rotating from landscape back to portrait.

Everything runs fine, and renders correctly. However this complaint worries us. Anyone else have any ideas or solutions?

21条回答
Root(大扎)
2楼-- · 2020-05-17 00:30

I know this is an old question, but I just got the same problem and spent an hour to solve it. My problem was that, it seems the UICollectionView's frame size is always wrong (the height doesn't match the container) while I set the frame size right before the UICollectionView Flow layout delegate is called. So, I set the UICollectionView frame size again on the method :

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

And that did the trick. The height is now showing correctly and the warning is gone.

查看更多
ゆ 、 Hurt°
3楼-- · 2020-05-17 00:35

Just to suppress warning and (probably, not sure) improve performance you could before returning size in

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

check if view controller is in process of rotation and if it is return some relatively small size like CGSizeMake(0.1, 0.1)

查看更多
不美不萌又怎样
4楼-- · 2020-05-17 00:36

I encountered this same issue. If the collection view was displayed when in portrait orientation, the cells would disappear when rotated to landscape. I did a combination of the other answers here to fix this.

I set my view (the one that contains the UICollectionView) up to receive the UIDeviceOrientationDidChangeNotification notification. In the method that responds to that notification, after the UICollectionView frame was adjusted, I did the following:

- (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];
}

Note that the frame of the UICollectionView is being set automatically upon rotation because its resizingMask is set to this upon initialization:

self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
查看更多
贼婆χ
5楼-- · 2020-05-17 00:37

I solved it.

You should just let the height of flowLayout less than collcetionView.frame.size.height.

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


 collectionView.frame = CGRectMake(12, 380, 290, 80);
查看更多
走好不送
6楼-- · 2020-05-17 00:37

Try this...

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

layout.itemSize = CGSizeMake(0.1, 0.1);

It's works for me.

查看更多
够拽才男人
7楼-- · 2020-05-17 00:37

try at the end of didRotateFromInterfaceOrientation:

[self.collectionView setNeedsLayout]

if it does not work try to move all this stuff from didRotateFromInterfaceOrientation to willRotateToInterfaceOrientation

查看更多
登录 后发表回答