2015-12-07 24 views
29

ビューを整然とした列に配置できるように、UICollectionViewを作成しました。私は500ピクセル以上の幅のデバイス上に単一の列があることを望みます。UICollectionView - デバイス上のセルのサイズを変更する - Swift

これを達成するために、私はこの関数を作成:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { 
    let size = collectionView.frame.width 
    if (size > 500) { 
     return CGSize(width: (size/2) - 8, height: (size/2) - 8) 
    } 
    return CGSize(width: size, height: size) 
} 

最初のロード時に予想されるように、これは動作しますが、私は、デバイスを回転させたときただし、計算は常に再び起こる、とビュードンはありませんが期待どおりに常に再描画しません。ここでは、デバイスを回転させたときのために私のコードです:私は何かを再描画するために忘れてしまったと仮定してい

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) { 
    collectionView.collectionViewLayout.invalidateLayout() 
    self.view.setNeedsDisplay() 
} 

は、私はよく分かりません。どんなアイデアも非常に感謝して受け取ります!

答えて

18

viewWillLayoutSubviewsを使用することがあります。 This questionは役立つはずですが、ビューコントローラビューがそのサブビューをレイアウトしようとしているときはいつでも、これは基本的に呼び出されます。

だからあなたのコードは次のようになります。

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 

    guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { 
    return 
    } 

    if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) { 
    //here you can do the logic for the cell size if phone is in landscape 
    } else { 
    //logic if not landscape 
    } 

    flowLayout.invalidateLayout() 
} 
+6

あなたが無限ループに入ります。 – valvoline

+3

@valvolineが正しいと確信していないので、無限ループが発生しますが、必要以上に頻繁にcollectionviewレイアウトを無効にするため、パフォーマンスの問題が発生する可能性があります。 'viewWillTransitionToSize'を使うほうがずっと良いです。 – JosephH

+3

このコードは、無限ループを引き起こします。正解ではありません。 – Josh

13

私は同じことでviewWillTransitionToSizeを使用する傾向があり、単にそこに呼び出しinvalidateLayout()を作りました。これを行うために

22

おそらく最もストレートな方法は、viewWillTransitionToSize中にinvalidateLayoutをすることです:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    super.viewWillTransition(to: size, with: coordinator) 
    guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { 
     return 
    } 
    flowLayout.invalidateLayout() 
} 
0

私はUICollectionViewサブクラス内の項目のサイズを調整するタスクを持っていました。これに最も適した方法はsetFrameです。プロパティcollectionViewFlowLayout ViewControllerから渡されました(私の場合、デフォルトのフローレイアウトのコンセントでした)。

// .h 
@property (nonatomic, weak) UICollectionViewFlowLayout *collectionViewFlowLayout; 

// .m 
- (void)setFrame:(CGRect)frame { 
    if (!CGSizeEqualToSize(frame.size, self.frame.size)) { 
     collectionViewFlowLayout.itemSize = 
     CGSizeMake((UIDeviceOrientationIsLandscape(UIDevice.currentDevice.orientation) ? (frame.size.width - 10)/2 : frame.size.width), collectionViewFlowLayout.itemSize.height); 
    } 
    [super setFrame:frame]; 
} 
0

traitCollectionDidChange方法ではなくviewWillLayoutSubviewsのにも使用されることがあります。

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 
    super.traitCollectionDidChange(previousTraitCollection) 

    guard let previousTraitCollection = previousTraitCollection, traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass || 
     traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass else { 
      return 
    } 

    if traitCollection.horizontalSizeClass == .regular && traitCollection.verticalSizeClass == .regular { 
     // iPad portrait and landscape 
     // do something here... 
    } 
    if traitCollection.horizontalSizeClass == .compact && traitCollection.verticalSizeClass == .regular { 
     // iPhone portrait 
     // do something here... 
    } 
    if traitCollection.horizontalSizeClass == .regular && traitCollection.verticalSizeClass = .compact { 
     // iPhone landscape 
     // do something here... 
    } 
    collectionView?.collectionViewLayout.invalidateLayout() 
    collectionView?.reloadData() 
} 
0

あなたはマスクのコンテンツを作成し、それがcollectionViewに移動することができます。ランドスケープ/ポートレートアニメーションが終了した後は、できるだけ早く削除する必要があります。ここで

は一例です。このアプローチを使用することにより

@property (strong, nonatomic) UIImageView *maskImage; 

......... 

- (UIImageView *) imageForCellAtIndex: (NSInteger) index { 
    UICollectionView *collectionView = self.pagerView.test; 
    FSPagerViewCell *cell = nil; 
    NSArray *indexPaths = [collectionView indexPathsForVisibleItems]; 
    for (NSIndexPath *indexPath in indexPaths) { 
     if (indexPath.item == index) { 
      cell = (FSPagerViewCell *)[collectionView cellForItemAtIndexPath: indexPath]; 
      break; 
     } 
    } 
    if (cell) { 
     return cell.imageView; 
    } 
    return nil; 
} 


- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator 

{ 
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; 

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) 
    { 
     UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 
     [self test_didRotateFromInterfaceOrientation: orientation]; 

     UIImageView *imageView = [self imageForCellAtIndex: self.pagerView.currentIndex]; 
     if (imageView) { 
       UIImageView *imageView = [self imageForCellAtIndex: self.pagerView.currentIndex]; 
       CGSize itemSize = self.pagerView.itemSize; 
       UIImageView *newImage = [[UIImageView alloc] initWithImage: imageView.image]; 
       [newImage setFrame: CGRectMake((_contentView.bounds.size.width - itemSize.width)/2.0f, 0, itemSize.width, itemSize.height)]; 
       newImage.contentMode = imageView.contentMode; 
       newImage.clipsToBounds = imageView.clipsToBounds; 
       newImage.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 
       [self.pagerView addSubview: newImage]; 

       self.maskImage = newImage; 
     } 

     [self.pagerView.test performBatchUpdates:^{ 
      [self.pagerView.test setCollectionViewLayout:self.pagerView.test.collectionViewLayout animated:YES]; 
     } completion:nil]; 
     // do whatever 
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) 
    { 
     [self.maskImage removeFromSuperview]; 
    }]; 
} 
関連する問題