Solution 1, “just snap”
If you only need to make sure that the contentOffset ends in the correct position, you can subclass UICollectionViewLayout and implement the targetContentOffsetForProposedContentOffset: method. For example, you can do something like this to calculate the page:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset { NSInteger page = ceil(proposedContentOffset.x / [self.collectionView frame].size.width); return CGPointMake(page * [self.collectionView frame].size.width, 0); }
But the problem you will encounter is that the animation for this transition is extremely strange. What I do in my case (this is almost the same as yours):
Solution 2, smooth animation
1) First, I set the size of the cell that the collectionView: layout: sizeForItemAtIndexPath: delegate method can control:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.view bounds].size; }
Note that [self.view bounds] will change according to the rotation of the device.
2) When the device is about to start spinning, I add an imageView on top of the collection view with all the masks for resizing. This view will actually hide the weirdness collectionView (because it sits on top of it), and since the willRotatoToInterfaceOrientation: method is called inside the animation block, it will rotate accordingly. I also save the following contentOffset in accordance with the indexPath shown, so I can fix the contentOffset after the rotation is done:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { // Gets the first (and only) visible cell. NSIndexPath *indexPath = [[self.collectionView indexPathsForVisibleItems] firstObject]; KSPhotoViewCell *cell = (id)[self.collectionView cellForItemAtIndexPath:indexPath]; // Creates a temporary imageView that will occupy the full screen and rotate. UIImageView *imageView = [[UIImageView alloc] initWithImage:[[cell imageView] image]]; [imageView setFrame:[self.view bounds]]; [imageView setTag:kTemporaryImageTag]; [imageView setBackgroundColor:[UIColor blackColor]]; [imageView setContentMode:[[cell imageView] contentMode]]; [imageView setAutoresizingMask:0xff]; [self.view insertSubview:imageView aboveSubview:self.collectionView]; // Invalidate layout and calculate (next) contentOffset. contentOffsetAfterRotation = CGPointMake(indexPath.item * [self.view bounds].size.height, 0); [[self.collectionView collectionViewLayout] invalidateLayout]; }
Note that my subclass of UICollectionViewCell has a public imageView property.
3) Finally, the last step is to “snap” the content offset to a valid page and delete the temporary image.
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [self.collectionView setContentOffset:contentOffsetAfterRotation]; [[self.view viewWithTag:kTemporaryImageTag] removeFromSuperview]; }
fz. Mar 11 '14 at 20:25 2014-03-11 20:25
source share