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条回答
对你真心纯属浪费
2楼-- · 2020-05-17 00:23

In

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

I called the, [UICollectionViewLayout invalidateLayout] and seems to work good.

查看更多
爷的心禁止访问
3楼-- · 2020-05-17 00:25

You can subclass UICollectionView and override setBounds:. There before calling [super setBounds:] the item size can be adjusted to the new bounds.
You should check whether the size of the bounds has changed, because setBounds: is invoked also while scrolling.

查看更多
成全新的幸福
4楼-- · 2020-05-17 00:27

This works for me: (and hope it also works for you!)

- (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); 
}
查看更多
放荡不羁爱自由
5楼-- · 2020-05-17 00:27

Following code fixed it for me:

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.collectionView.frame.size;
}
查看更多
冷血范
6楼-- · 2020-05-17 00:27

Note: In my case, I discovered that we were setting the preferredContentSize property of the UIViewController in question. If you find this to be your case, you might have to deal with the following method of the UICollectionViewDelegateFlowLayout protocol:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGSize size = collectionViewLayout.collectionView.bounds.size;
    ...
    return size;
}
查看更多
男人必须洒脱
7楼-- · 2020-05-17 00:28

I faced the same problem. here is how i solved it. hope it helps

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

    [self.collectionView reloadData];
}
查看更多
登录 后发表回答