2012-11-21 28 views
61

我試圖在UICollectionViewController中處理接口方向更改。我試圖實現的是,我想要在接口旋轉後有相同的 contentOffset。意思是說,它應該根據邊界變化的比例來改變。在旋轉接口方向時保持UICollectionView中的contentOffset

在縱向與內容的偏移開始{bounds.size.width * 2,0} ...

UICollectionView in portait

...應該產生的內容的景觀{邊界偏移也。 size.width * 2,0}(反之亦然)。

UICollectionView in landscape

計算新的偏移量是沒有問題的,但不知道在哪裏(或者)來設置它,以獲得平滑的動畫。我在做什麼這樣的票價在willRotateToInterfaceOrientation:duration:無效的佈局和重置內容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]; 
} 

這改變了內容的旋轉後偏移。

如何在旋轉過程中設置它?我嘗試在willAnimateRotationToInterfaceOrientation:duration:中設置新的內容偏移量,但這會導致非常奇怪的行爲。

一個例子可以在我的項目GitHub中找到。

+7

你找到了一個解決方案? – Ghar

回答

-2

你可能想試試這個未經測試的代碼:

- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation 
           duration: (NSTimeInterval)   duration 
{ 
    [UIView animateWithDuration: duration 
         animation: ^(void) 
    { 
     CGPoint newContentOffset = CGPointMake(self.scrollPositionBeforeRotation.x * 
               self.collectionView.contentSize.height, 
               self.scrollPositionBeforeRotation.y * 
               self.collectionView.contentSize.width); 
     [self.collectionView setContentOffset: newContentOffset 
            animated: YES]; 
    }]; 
} 
0

我的方法是使用UICollectionViewFlowlayout對象。

設置ojbect行間距,如果它水平滾動。

[flowLayout setMinimumLineSpacing:26.0f]; 

如果垂直滾動,則設置它的相互間距。

[flowLayout setMinimumInteritemSpacing:0.0f]; 

請注意,當您旋轉屏幕時,它的行爲會有所不同。在我的情況下,我把它水平滾動,所以minimumlinespacing是26.0f。然後,當它轉向風景方向時,它看起來很可怕。我必須檢查旋轉,併爲該方向設置minimumlinespacing 0.0f以使其正確。

就是這樣!簡單。

0

我有我的項目的問題,我用UICollectionView兩個不同的佈局。

mCustomCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"LandScapeCell" forIndexPath:indexPath]; 

theCustomCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"PortraitCell" forIndexPath:indexPath]; 

然後檢查它的每個方向並使用您的配置爲每個方向。

0
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 
    CGSize pnt = CGSizeMake(70, 70); 
    return pnt; } 

-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { 

// UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>) 
    return UIEdgeInsetsMake(3, 0, 3, 0); } 

這樣你就可以調整你的單元格的內容偏移量和大小。

0

使用<CollectionViewDelegateFlowLayout>和在的CollectionView的方法didRotateFromInterfaceOrientation:重裝數據。

執行collectionView:layout:sizeForItemAtIndexPath:方法<CollectionViewDelegateFlowLayout>並在該方法中驗證接口方向並應用您的自定義大小的每個單元格。

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 

    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 

    if (UIInterfaceOrientationIsPortrait(orientation)) { 

     return CGSizeMake(CGFloat width, CGFloat height); 

    } else { 

     return CGSizeMake(CGFloat width, CGFloat height); 

    } 

} 
0

具有其中我用這個

- (void)setFrame:(CGRect)frame 
{ 
    CGFloat currentWidth = [self frame].size.width; 
    CGFloat offsetModifier = [[self collectionView] contentOffset].x/currentWidth; 

    [super setFrame:frame]; 

    CGFloat newWidth = [self frame].size.width; 

    [[self collectionView] setContentOffset:CGPointMake(offsetModifier * newWidth, 0.0f) animated:NO]; 
} 

這是一個包含一個的CollectionView的圖類似的情況。 在上海華我還要這樣做

- (void)setFrame:(CGRect)frame 
{  
    UICollectionViewFlowLayout *collectionViewFlowLayout = (UICollectionViewFlowLayout *)[_collectionView collectionViewLayout]; 

    [collectionViewFlowLayout setItemSize:frame.size]; 

    [super setFrame:frame]; 
} 

這是爲了調節泡孔尺寸爲全屏(全視角是精確的;))。如果你不這樣做,在這裏有很多的錯誤信息可能會出現關於該小區大小比的CollectionView做大,對這個行爲是沒有定義和唧唧歪歪.....

這些的方法能關閉過程將合併到的CollectionView的一個子類,或者在包含的CollectionView的看法,但我目前的項目,這是邏輯的路要走。

7

我認爲正確的解決辦法是重寫- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset方法在子類UICollectionViewFlowLayout

從文檔:

在佈局過程中更新,或者佈局之間轉換時,該 集合視圖調用此方法讓您有機會到 變化所提出的內容偏移在動畫的最後使用。 如果動畫或過渡可能 原因項目被定位在一個方式,是不是最佳的您 設計你可能重寫此方法。

17

解決方案1,「剛捕捉」

如果你需要的是隻是爲了確保contentOffset在正確的位置結束,您可以創建UICollectionViewLayout的一個子類,並實現targetContentOffsetForProposedContentOffset:方法。例如,你可以做這樣的事情來計算頁:

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset 
{ 
    NSInteger page = ceil(proposedContentOffset.x/[self.collectionView frame].size.width); 
    return CGPointMake(page * [self.collectionView frame].size.width, 0); 
} 

但是,你要面對的問題是,對於過渡動畫是非常奇怪的。我做我的情況是什麼(這幾乎是一樣的你)是:

方案2,「流暢的動畫」

1)首先,我設置單元格的大小,可以通過的CollectionView管理:佈局:sizeForItemAtIndexPath:委託方法如下:

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

注意,[self.view界限]將根據設備旋轉而改變。

2)當設備即將旋轉時,我使用所有調整大小遮罩在集合視圖頂部添加imageView。這個視圖實際上會隱藏collectionView怪異(因爲它位於頂部),並且由於willRotatoToInterfaceOrientation:方法在動畫塊內被調用,它將相應地旋轉。我根據顯示indexPath這樣我就可以修復contentOffset一旦旋轉完成也保持未來contentOffset:

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

注意,我UICollectionViewCell的子類有一個公共ImageView的屬性。

3)最後,最後一步是將內容偏移量「捕捉」到有效頁面並刪除臨時圖像視圖。

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{ 
    [self.collectionView setContentOffset:contentOffsetAfterRotation]; 
    [[self.view viewWithTag:kTemporaryImageTag] removeFromSuperview]; 
} 
+0

這件作品很有魅力,謝謝。 – Moritz

+1

你的答案很棒!但是你錯過了在willRotateToInterfaceOrientation和didRotateFromInterfaceOrientation中超級調用。 –

+0

這不適用於我,因爲它是,我改變它不計算旋轉後的偏移量,而是存儲獲取單元格信息時拉出的NSIndexPath,而不是設置偏移量滾動到沒有動畫的偏移量。如果有人有興趣,我可以用代碼(swift)將實際答案放在一起。 – mwright

12

上面的「只是快照」答案對我來說不起作用,因爲它經常不會在旋轉之前在視圖中的項目結束。所以我導出了一個使用焦點項目(如果設置)來計算內容偏移量的流佈局。我將該項目設置在willAnimateRotationToInterfaceOrientation中,並在didRotateFromInterfaceOrientation中將其清除。嵌入式調整似乎需要在IOS7上,因爲Collection視圖可以在頂部欄下佈局。

@interface HintedFlowLayout : UICollectionViewFlowLayout 
@property (strong)NSIndexPath* pathForFocusItem; 
@end 

@implementation HintedFlowLayout 

-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset 
{ 
    if (self.pathForFocusItem) { 
     UICollectionViewLayoutAttributes* layoutAttrs = [self layoutAttributesForItemAtIndexPath:self.pathForFocusItem]; 
     return CGPointMake(layoutAttrs.frame.origin.x - self.collectionView.contentInset.left, layoutAttrs.frame.origin.y-self.collectionView.contentInset.top); 
    }else{ 
     return [super targetContentOffsetForProposedContentOffset:proposedContentOffset]; 
    } 
} 
@end 
+0

這對我有用。 – SwampThingTom

+0

迄今爲止最簡單的解決方案 –

0

什麼工作對我來說是這樣的:

  1. 設置你的我的單元格的大小從你我UICollectionViewDelegateFlowLayout方法

    func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize 
    { 
        return collectionView.bounds.size 
    } 
    
  2. 之後,我實現willRotateToInterfaceOrientationToInterfaceOrientation:duration:這樣

    override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) 
    { 
        let currentPage = Int(collectionView.contentOffset.x/collectionView.bounds.size.width) 
    
        var width = collectionView.bounds.size.height 
        UIView.animateWithDuration(duration) { 
         self.collectionView.setContentOffset(CGPointMake(width * CGFloat(currentPage), 0.0), animated: false) 
         self.collectionView.collectionViewLayout.invalidateLayout() 
        } 
    } 
    

上面的代碼是在斯威夫特,但你明白了吧,很容易給「翻譯」

2

這項工作就像一個魅力:

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

這個問題困擾了我有點爲好。回答最高的投票回答對我來說似乎有點太過分,所以我只是簡單地把它弄昏了一下,只是分別在輪播之前和之後改變收集視圖的alpha值。我也不會動畫內容偏移更新。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
self.collectionView.alpha = 0; 
[self.collectionView.collectionViewLayout invalidateLayout]; 

self.scrollPositionBeforeRotation = CGPointMake(self.collectionView.contentOffset.x/self.collectionView.contentSize.width, 
               self.collectionView.contentOffset.y/self.collectionView.contentSize.height); 
} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation; 
{ 
CGPoint newContentOffset = CGPointMake(self.scrollPositionBeforeRotation.x * self.collectionView.contentSize.width, 
             self.scrollPositionBeforeRotation.y * self.collectionView.contentSize.height); 

[self.collectionView setContentOffset:newContentOffset animated:NO]; 
self.collectionView.alpha = 1; 
} 

相當順利,不那麼哈。

1

如果發現使用targetContentOffsetForProposedContentOffset在所有情況下都不起作用,並且使用didRotateFromInterfaceOrientation的問題是它會產生可視的工件。我的完美工作代碼如下:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
    _indexPathOfFirstCell = [self indexPathsForVisibleItems].firstObject; 
} 

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
    if (_indexPathOfFirstCell) { 
     [UIView performWithoutAnimation:^{ 
      [self scrollToItemAtIndexPath:self->_indexPathOfFirstCell atScrollPosition:UICollectionViewScrollPositionTop animated:NO]; 
     }]; 
     _indexPathOfFirstCell = nil; 
    } 
} 

的關鍵是使用willRotateToInterfaceOrientation方法來確定要滾動並willAnimationRotationToInterfaceOrientation重新計算其在視圖中的一部分時,該觀點已經改變了它的大小(當這個方法被框架調用時邊界已經改變了)並且實際上沒有動畫地滾動到新的位置。在我的代碼中,我使用第一個視覺單元的索引路徑來做到這一點,但contentOffset.y/contentSize.height的百分比也會以稍微不同的方式完成工作。

+0

不要忘記,旋轉API已被棄用iOS 8] –

10

對於使用的iOS 8+那些,willRotateToInterfaceOrientationdidRotateFromInterfaceOrientation被棄用。

您應該使用現在以下幾點:

/* 
This method is called when the view controller's view's size is changed by its parent (i.e. for the root view controller when its window rotates or is resized). 
If you override this method, you should either call super to propagate the change to children or manually forward the change to children. 
*/ 
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator 
{ 
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; 

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
     // Update scroll position during rotation animation 
     self.collectionView.contentOffset = (CGPoint){contentOffsetX, contentOffsetY}; 
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
     // Whatever you want to do when the rotation animation is done 
    }]; 
} 

斯威夫特3:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    super.viewWillTransition(to: size, with: coordinator) 

    coordinator.animate(alongsideTransition: { (context:UIViewControllerTransitionCoordinatorContext) in 
     // Update scroll position during rotation animation 
    }) { (context:UIViewControllerTransitionCoordinatorContext) in 
     // Whatever you want to do when the rotation animation is done 
    } 
} 
+0

非常感謝你 – Petar

+1

全屏單元格如何?當我滑到第二個或第三個單元格,並旋轉時,我看到最後一個單元格,並在第二個單元格上:( – iTux

4

我使用FZ的變體。答案(的iOS 7 & 8):

循環之前:

  1. 存儲當前可見的索引路徑
  2. 創建的集合視圖的頂部放置一個的UIImageView與它的的CollectionView
  3. 快照

旋轉後:

  1. 滾動到存儲的索引
  2. 刪除圖像視圖。

    @property (nonatomic) NSIndexPath *indexPath; 
    
    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
               duration:(NSTimeInterval)duration { 
        self.indexPathAfterRotation = [[self.collectionView indexPathsForVisibleItems] firstObject]; 
    
        // Creates a temporary imageView that will occupy the full screen and rotate. 
        UIGraphicsBeginImageContextWithOptions(self.collectionView.bounds.size, YES, 0); 
        [self.collectionView drawViewHierarchyInRect:self.collectionView.bounds afterScreenUpdates:YES]; 
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
        UIGraphicsEndImageContext(); 
    
        UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 
        [imageView setFrame:[self.collectionView bounds]]; 
        [imageView setTag:kTemporaryImageTag]; 
        [imageView setBackgroundColor:[UIColor blackColor]]; 
        [imageView setContentMode:UIViewContentModeCenter]; 
        [imageView setAutoresizingMask:0xff]; 
        [self.view insertSubview:imageView aboveSubview:self.collectionView]; 
    
        [[self.collectionView collectionViewLayout] invalidateLayout]; 
    } 
    
    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 
        [self.collectionView scrollToItemAtIndexPath:self.indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO]; 
    
        [[self.view viewWithTag:kTemporaryImageTag] removeFromSuperview]; 
    } 
    
+1

我最終使用類似這樣的事情,希望我先看到你的第一個 – mwright

2

旋轉接口的方向後,UICollectionViewCell通常移動到另一個位置,因爲我們將不會更新contentSize和contentOffset。

所以可見的UICollectionViewCell總是不在預期的位置。

我們預計形象,遵循

Orientation which we expected

UICollectionView必須委派功能『UICollectionViewDelegateFlowLayout』的[的CollectionView sizeForItemAtIndexPath]可見UICollectionView。

而且您應該計算此功能中的項目大小。

自定義UICollectionViewFlowLayout必須覆蓋如下功能。

  1. -(void)prepareLayout

    。設置itemSize,scrollDirection等。

  2. -(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity

    。計算頁碼或計算可見內容偏移量。

  3. -(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset

    。返回視覺內容偏移。

  4. -(CGSize)collectionViewContentSize

    。返回collectionView的總內容大小。

你的viewController必須重寫『willRotateToInterfaceOrientation』,並在這個函數 你應該調用函數[XXXCollectionVew.collectionViewLayout的invalidateLayout]

但在iOS 9中不推薦使用「willRotateToInterfaceOrientation」,也可以不同的方式調用函數[XXXCollectionVew.collectionViewLayout invalidateLayout]。

這裏有一個例子如下: https://github.com/bcbod2002/CollectionViewRotationTest

+1

請描述你做了什麼或告訴你的項目的任何事情! –

0

「公正啪」的答案是正確的做法,並不需要用快照覆蓋IMO額外的平滑。但是有一個問題解釋了爲什麼有些人看到在某些情況下正確的頁面沒有滾動到。計算頁面時,您想要使用高度而不是寬度。爲什麼?因爲視圖幾何已經旋轉了targetContentOffsetForProposedContentOffset被調用的時間,所以寬度現在是高度。舍入比天花板更明智。所以:

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset 
{ 
    NSInteger page = round(proposedContentOffset.x/self.collectionView.bounds.size.height); 
    return CGPointMake(page * self.collectionView.bounds.size.width, 0); 
} 
0

我解決了這個問題,下面的步驟:

  1. 計算當前滾動的NSIndexPath
  2. 禁用滾動和分頁在UICollectionView
  3. 應用新的流式佈局,以UICollectionView
  4. 在UICollectionView
  5. 滾動UICollectionView啓用滾動和分頁目前NSIndexPath

這裏是代碼模板演示上面的步驟:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
          duration:(NSTimeInterval)duration; 
{ 
    //Calculating Current IndexPath 
    CGRect visibleRect = (CGRect){.origin = self.yourCollectionView.contentOffset, .size = self.yourCollectionView.bounds.size}; 
    CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect)); 
    self.currentIndexPath = [self.yourCollectionView indexPathForItemAtPoint:visiblePoint]; 

    //Disable Scrolling and Pagination 
    [self disableScrolling]; 

    //Applying New Flow Layout 
    [self setupNewFlowLayout]; 

    //Enable Scrolling and Pagination 
    [self enableScrolling]; 
} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation; 
{ 
    //You can also call this at the End of `willRotate..` method. 
    //Scrolling UICollectionView to current Index Path 
    [self.yourCollectionView scrollToItemAtIndexPath:self.currentIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO]; 
} 

- (void) disableScrolling 
{ 
    self.yourCollectionView.scrollEnabled = false; 
    self.yourCollectionView.pagingEnabled = false; 
} 

- (void) enableScrolling 
{ 
    self.yourCollectionView.scrollEnabled = true; 
    self.yourCollectionView.pagingEnabled = true; 
} 

- (void) setupNewFlowLayout 
{ 
    UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc] init]; 
    flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); 
    flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 
    flowLayout.minimumInteritemSpacing = 0; 
    flowLayout.minimumLineSpacing = 0; 
    [flowLayout setItemSize:CGSizeMake(EXPECTED_WIDTH, EXPECTED_HEIGHT)]; 

    [self.yourCollectionView setCollectionViewLayout:flowLayout animated:YES]; 
    [self.yourCollectionView.collectionViewLayout invalidateLayout]; 
} 

我希望這有助於。

2

爲了繼續使用troppoli's解決方案,您可以在自定義類中設置偏移量,而無需擔心要記住在視圖控制器中實現代碼。當旋轉設備後,prepareForAnimatedBoundsChange應該被調用,然後在完成旋轉後調用finalizeAnimatedBoundsChange

@interface OrientationFlowLayout() 

@property (strong)NSIndexPath* pathForFocusItem; 

@end 

@implementation OrientationFlowLayout 

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset { 
    if (self.pathForFocusItem) { 
     UICollectionViewLayoutAttributes* layoutAttrs = [self layoutAttributesForItemAtIndexPath: 
                 self.pathForFocusItem]; 
     return CGPointMake(layoutAttrs.frame.origin.x - self.collectionView.contentInset.left, 
          layoutAttrs.frame.origin.y - self.collectionView.contentInset.top); 
    } 
    else { 
     return [super targetContentOffsetForProposedContentOffset:proposedContentOffset]; 
    } 
} 

- (void)prepareForAnimatedBoundsChange:(CGRect)oldBounds { 
    [super prepareForAnimatedBoundsChange:oldBounds]; 
    self.pathForFocusItem = [[self.collectionView indexPathsForVisibleItems] firstObject]; 
} 

- (void)finalizeAnimatedBoundsChange { 
    [super finalizeAnimatedBoundsChange]; 
    self.pathForFocusItem = nil; 
} 

@end 
+0

是呼籲超級需要雖然? –

0
斯威夫特3.

你應該跟蹤哪些細胞項目(頁)被旋轉之前通過indexPath.item提出,x座標或別的東西。 然後,在你UICollectionView:

override func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { 

    let page:CGFloat = pageNumber // your tracked page number eg. 1.0 
    return CGPoint(x: page * collectionView.frame.size.width, y: -(topInset)) 
    //the 'y' value would be '0' if you don't have any top EdgeInset 
} 

在我來說,我在無效viewDidLayoutSubviews(佈局),所以collectionView.frame.size.width是已被旋轉的collectionVC視野的寬度。

8

這裏是代碼雨燕3.1

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
{ 
    super.viewWillTransition(to: size, with: coordinator) 
    let offset = self.collectionView?.contentOffset; 
    let width = self.collectionView?.bounds.size.width; 

    let index  = round(offset!.x/width!); 
    let newOffset = CGPoint(x: index * size.width, y: offset!.y) 

    self.collectionView?.setContentOffset(newOffset, animated: false) 


    coordinator.animate(alongsideTransition: { (context) in 
     self.collectionView?.reloadData() 
     self.collectionView?.setContentOffset(newOffset, animated: false) 
    }, completion: nil) 
} 
+0

你是最好的 –

+0

準確的答案。非常感謝! –

+1

不適用於iPhone X – guidev

相關問題