Abdelrahman
Abdelrahman

Reputation: 1027

How to adjust UICollectionView contentOffset after rotation?

I have a UICollectionView with paging enabled, the page contentOffset is not correctly adjusted after rotation.

I overrided the two following methods

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

collectionView.collectionViewLayout.invalidateLayout()
}

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {

let width = collectionView.bounds.width

var frame = collectionView.frame
frame.origin.x = width * CGFloat(pageControl.currentPage)
frame.origin.y = 0

collectionView.scrollRectToVisible(frame, animated: false)
}

but still have the same problem.

What needs to be done for these changes to adjust contentOffset of the current page correctly when the device is rotated?

on landscape the page is positioned correctly , but when the device is rotated to portrait the page position is incorrect as in the following images

enter image description here

enter image description here

Upvotes: 1

Views: 2560

Answers (1)

Andrew  Egorov
Andrew Egorov

Reputation: 71

I've fixed this problem with the next code:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    CGPoint offset = self.collectionView.contentOffset;
    CGFloat width = self.collectionView.bounds.size.width;

    NSInteger index = round(offset.x / width);
    CGPoint newOffset = CGPointMake(index * size.width, offset.y);

    [self.collectionView setContentOffset:newOffset animated:NO];

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        [self.collectionView reloadData];
        [self.collectionView setContentOffset:newOffset animated:NO];
    } completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {

    }];
}

But take into account that my photos is scrolled horizontally.

Animation during this transition is not very smooth, but acceptable. If you want to make it excellent you can hide a collectionView before a rotation and place an image view with current image on the screen. Image view should rotate without any problem. After rotation you can run an appropriate code from above and after that remove an image view from the screen. I have not tried to implement this idea yet, but it should look like:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    CGPoint offset = self.collectionView.contentOffset;
    CGFloat width = self.collectionView.bounds.size.width;

    NSInteger index = round(offset.x / width);
    CGPoint newOffset = CGPointMake(index * size.width, offset.y);

    //here you should create an image view and place it on the screen
    //without animation, you should also make constraints for it
    //you also should hide the collection view

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {

    } completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        [self.collectionView reloadData];
        [self.collectionView setContentOffset:newOffset animated:NO];
        //here you should remove the image view and show the collection view

    }];
}

Sorry for Objective C :).

Upvotes: 3

Related Questions