I'm trying to handle interface orientation changes in a UICollectionViewController. What I'm trying to achieve is, that I want to have the same contentOffset after an interface rotation. Meaning, that it should be changed corresponding to the ratio of the bounds change.
Starting in portrait with a content offset of {bounds.size.width * 2, 0} …
… should result to the content offset in landscape also with {bounds.size.width * 2, 0} (and vice versa).
Calculating the new offset is not the problem, but don't know, where (or when) to set it, to get a smooth animation. What I'm doing so fare is invalidating the layout in willRotateToInterfaceOrientation:duration:
and resetting the content offset in didRotateFromInterfaceOrientation:
:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration;
{
self.scrollPositionBeforeRotation = CGPointMake(self.collectionView.contentOffset.x / self.collectionView.contentSize.width,
self.collectionView.contentOffset.y / self.collectionView.contentSize.height);
[self.collectionView.collectionViewLayout invalidateLayout];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;
{
CGPoint newContentOffset = CGPointMake(self.scrollPositionBeforeRotation.x * self.collectionView.contentSize.width,
self.scrollPositionBeforeRotation.y * self.collectionView.contentSize.height);
[self.collectionView newContentOffset animated:YES];
}
This changes the content offset after the rotation.
How can I set it during the rotation? I tried to set the new content offset in willAnimateRotationToInterfaceOrientation:duration:
but this results into a very strange behavior.
An example can be found in my Project on GitHub.
I had got some troubles with
animateAlongsideTransition
block inanimateAlongsideTransition
(see the code below).Pay attention, that it is called during (but not before) the animation My task was update the table view scroll position using scrolling to the top visible row (I’ve faced with the problem on iPad when table view cells shifted up when the device rotation, therefore I was founding the solution for that problem). But may be it would be useful for contentOffset too.
I tried to solve the problem by the following way:
But it didn’t work. For instance, index path of the top cel was (0, 20). But when the device rotation animateAlongsideTransition block was called and [[weakSelf.tableView indexPathsForVisibleRows] firstObject] returned index path (0, 27).
I thought the problem was in retrieving index paths to
weakSelf
. Therefore to solve the problem I’ve movedself.topVisibleRowIndexPath
before[coordinator animateAlongsideTransition: completion]
method calling:And the other interesting thing that I’ve discovered is that the deprecated methods
willRotateToInterfaceOrientation
andwillRotateToInterfaceOrientation
are still successful called in iOS later 8.0 when methodviewWillTransitionToSize
is not redefined.So the other way to solve the problem in my case was to use deprecated method instead of new one. I think it would be not right solution, but it is possible to try if other ways don’t work :)
This work like a charm:
What does the job for me is this:
Set the size of your my cells from your my
UICollectionViewDelegateFlowLayout
methodAfter that I implement
willRotateToInterfaceOrientationToInterfaceOrientation:duration:
like thisThe above code is in Swift but you get the point and it's easy to "translate"
I had the issue with my project,i used two different layout for the UICollectionView.
Then Check it for each orientation and use your configuration for each orientation.
The "just snap" answer is the right approach and doesn't require extra smoothing with snapshot overlays IMO. However there's an issue which explains why some people see that the correct page isn't scrolled to in some cases. When calculating the page, you'd want to use the height and not the width. Why? Because the view geometry has already rotated by the time targetContentOffsetForProposedContentOffset is called, and so what was the width is now the height. Also rounding is more sensible than ceiling. So: