11

我有一个使用 aUICollectionView和 a的照片库视图UICollectionViewFlowLayout,它具有pagingEnabled并水平滚动,一次只显示一个视图。

在我尝试旋转它之前效果很好......

当我旋转设备时,willRotateToInterfaceOrientation:duration:我更新了它,collectionView.contentOffset所以它停留在正确的项目上,我调整了 currentCell 的大小,让它动画到新的维度。 问题出在两个状态之间的动画中,“先前”方向从左上角开始动画,并进入其他单元格的视图。 我做错了什么使得屏幕上的动画视图是FUBAR?

下面是它在行动中的样子:

http://www.smugmug.com/gallery/n-3F9kD/i-BwzRzRf/A(忽略断断续续的视频,那是 Quicktime 的错:p)

这是我的willAnimateRotationToInterfaceOrientation:duration

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

// Update the flowLayout's size to the new orientation's size
UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
    flow.itemSize = CGSizeMake(self.collectionView.frame.size.width, self.collectionView.frame.size.height);
} else {
    flow.itemSize = CGSizeMake(self.collectionView.frame.size.width, self.collectionView.frame.size.height);
}
self.collectionView.collectionViewLayout = flow;
[self.collectionView.collectionViewLayout invalidateLayout];

// Get the currently visible cell
PreviewCellView *currentCell = (PreviewCellView*)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:_currentIndex inSection:0]];

// Resize the currently index to the new flow's itemSize
CGRect frame = currentCell.frame;
frame.size = flow.itemSize;
currentCell.frame = frame;

// Keep the collection view centered by updating the content offset
CGPoint newContentOffset = CGPointMake(_currentIndex * frame.size.width, 0);
self.collectionView.contentOffset = newContentOffset;
}

据我所知,我在任何地方都找不到任何示例代码来说明如何制作优雅旋转的“照片库”风格的收藏视图。

4

3 回答 3

5

我为此苦苦挣扎了很长一段时间,直到我至少找到了这个“美容解决方法”:

在旋转期间在 collectionView 顶部添加带有当前图像(和正确的自动布局约束集)的全屏 UIImageView。像这样:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration: (NSTimeInterval)duration 
{

[self.collectionView.collectionViewLayout invalidateLayout];

    // show a UIImageView with the current image on top of the collectionView 
    // to cover the ugly animation
    self.imageViewOnTopOfCollectionView.image = [self imageForItemAtIndexPath:self.currentIndexPath];
    self.imageViewOnTopOfCollectionView.hidden = NO;

    // show a centered, very large 'fakeBackground' view on top of
    // the UICollectionView, but below the UIImageView
    self.fakeBackground.hidden = NO;
}

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    // ... set correct contentOffset

    // hide the fake views again
    self.imageViewOnTopOfCollectionView.hidden = YES;
    self.fakeBackground.hidden = YES;
}

一个大的“fakeBackground”将是一个额外的改进,以防止丑陋的集合视图动画的一部分在这个 imageViews 框架旋转时在它之外可见。例如,一个超大的(在所有维度上都大于视图的边界)UIView,其背景颜色与 collectionView 相同,z-Index 位于 collectionView 和 imageView 之间。

于 2013-09-24T20:42:37.387 回答
3

这项工作就像一个魅力:

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout     *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return self.view.bounds.size;
}

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {

    int currentPage = collectionMedia.contentOffset.x / collectionMedia.bounds.size.width;
    float width = collectionMedia.bounds.size.height;

    [UIView animateWithDuration:duration animations:^{
        [self.collectionMedia setContentOffset:CGPointMake(width * currentPage, 0.0) animated:NO];
        [[self.collectionMedia collectionViewLayout] invalidateLayout];
    }];
}
于 2014-11-12T13:34:50.650 回答
1

添加到@Goodsquirrel 的好答案,这是我使用当前 iOS8 API 和 Swift 实现它的方式:

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

    // show the dummy imageView
    self.imageViewOnTopOfCollectionView.image = self.imageForItemAtIndex(self.currentIndex)
    self.imageViewOnTopOfCollectionView.hidden = false;

    coordinator.animateAlongsideTransition({ (context) -> Void in
        // update the dummy imageView's frame
        var frame:CGRect = self.imageViewOnTopOfCollectionView.frame;
        frame.size = size;
        self.imageViewOnTopOfCollectionView.frame = frame;

        // update the flow's item size
        if let flow = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            flow.itemSize = size;
        }

        // scroll to the current index
        self.scrollToItem(self.currentIndex);
        }, completion: { (context) -> Void in
            // remove the dummy imageView
            self.imageViewOnTopOfCollectionView.hidden = true;
    });
}
于 2015-05-27T15:38:04.060 回答