Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collection View does not update layout at Rotation

This is the view of the app when it is in portrait mode. enter image description here

When it is rotated to landscape mode it looks like this

enter image description here

The view debugger shows that the UIWindow is not rotating as shown here enter image description here

The UICollectionViewController is created via StoryBoard. I've tried subclassing UICollectionViewFlowLayout that implements shouldInvalidateLayoutForBoundsChange, but it does not fix my issue.

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

Please provide ideas of what to check next or requests for additional code to debug.

Edit - As suggested by MirekE, I attempted to add constraints to the CollectionView but was unable. All of the options for Editor->Pin are unavailable for the CollectionView. enter image description here

Edit, response to Andrea -

I'm targeting iOS8.3. My understanding is that the main method called at rotation is viewWillTransitionToSize:withTransitionCoordinator:, which is from the UIContentContainer protocol. I've added the following to my CollectionViewController, but same problem persists

-(void)viewWillTransitionToSize:(CGSize)size
      withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator {
    [self.collectionView.collectionViewLayout invalidateLayout];
    [self.collectionView reloadData];
}
like image 501
Idr Avatar asked Jun 26 '15 04:06

Idr


2 Answers

I don't know which iOS version you ara targeting, but let me suppose that you know the rotation process and methods called in the view controller while it's happening.
In one of those methods you just need to call:

[self.collectionView.collectionViewLayout invalidateLayout];

and maybe depending on your layout -reloadData
No need to subclass.


EDIT

I use this method, I guess that is not working because you should relayout the collection after it has resized:

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

}


What I'm doing attach the layout invalidation process to the animation process.

like image 132
Andrea Avatar answered Nov 12 '22 12:11

Andrea


If you have custom implementation of UICollectionViewLayout, try to override methods:

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()

}

Cheers !

like image 35
Alex V Avatar answered Nov 12 '22 13:11

Alex V