如何定义旋转的CollectionView的大小

我有一个2个CollectionView控制器的视图控制器。

我想旋转只有一个集合视图调整到自定义大小,而另一个保持不变。

我曾尝试使用:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { // Adjust cell size for orientation if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) { return CGSizeMake(170.f, 170.f); } return CGSizeMake(192.f, 192.f); } 

但是,这只是改变了两个collectionviews。 我如何才能使它只针对一个集合?

inheritance人我的2美分 – 因为你的项目大小是静态的你为什么不设置collectionViewLayout的项目大小?

这样做会更快,而不是期望集合视图为每个单元调用其委托方法。

viewWillLayoutSubviews可用于在视图控制器上检测旋转。 可以在集合视图布局上使用invalidateLayout来强制它再次准备布局,使其在这种情况下使用新大小定位元素。

 - (void)viewWillLayoutSubviews; { [super viewWillLayoutSubviews]; UICollectionViewFlowLayout *flowLayout = (id)self.firstCollectionView.collectionViewLayout; if (UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation)) { flowLayout.itemSize = CGSizeMake(170.f, 170.f); } else { flowLayout.itemSize = CGSizeMake(192.f, 192.f); } [flowLayout invalidateLayout]; //force the elements to get laid out again with the new size } 

编辑:用Swift2.0例子更新

 override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return } if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) { flowLayout.itemSize = CGSize(width: 170, height: 170) } else { flowLayout.itemSize = CGSize(width: 192, height: 192) } flowLayout.invalidateLayout() } 

随着iOS 8以来的新API我使用:

Swift 3:

 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) updateCollectionViewLayout(with: size) } private func updateCollectionViewLayout(with size: CGSize) { if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { layout.itemSize = (size.width < size.height) ? itemSizeForPortraitMode : itemSizeForLandscapeMode layout.invalidateLayout() } } 

Objective-C的:

 - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; [self updateCollectionViewLayoutWithSize:size]; } - (void)updateCollectionViewLayoutWithSize:(CGSize)size { UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout; layout.itemSize = (size.width < size.height) ? itemSizeForPortraitMode : itemSizeForLandscapeMode; [layout invalidateLayout]; } 

已validation的答案效率不高

问题 – 使viewWillLayoutSubviews()中的布局无效是繁重的工作。 当ViewController被实例化时, viewWillLayoutSubviews()被多次调用。

我的解决scheme(Swift) – 在UICollectionViewDelegateFlowLayout中embedded你的尺寸操作。

 // Keep a local property that we will always update with the latest // view size. var updatedSize: CGSize! // Use the UICollectionViewDelegateFlowLayout to set the size of our // cells. func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { // We will set our updateSize value if it's nil. if updateSize == nil { // At this point, the correct ViewController frame is set. self.updateSize = self.view.frame.size } // If your collectionView is full screen, you can use the // frame size to judge whether you're in landscape. if self.updateSize.width > self.updateSize.height { return CGSize(width: 170, 170) } else { return CGSize(width: 192, 192) } } // Finally, update the size of the updateSize property, every time // viewWillTransitionToSize is called. Then performBatchUpdates to // adjust our layout. override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) self.updateSize = size self.collectionView!.performBatchUpdates(nil, completion: nil) } 

你可以改变你的if语句。 您将需要参考收集视图

 if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && collectionView == self.firstCollectionView) { return CGSizeMake(170.f, 170.f); } 

问题是,如何分隔sizeForItemAtIndexPath中的两个集合视图。 为什么不是这样?

  func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { if collectionView == firstCollectionView{ return CGSize(width: self.frame.width/3, height: 40) } else if collectionView == secondCollectionView{ return CGSize(width: self.frame.width, height: self.frame.height-2) } abort() } 

我已经通过检查设备的旋转,然后重新加载布局来解决这个问题。 检查屏幕大小并使用此大小显示我的单元格。

 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { //get new width of the screen screenRect = [[UIScreen mainScreen] bounds]; screenWidth = screenRect.size.width; //if landscape mode if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) { screenDivide = 5; } else { screenDivide = 3; } //reload the collectionview layout after rotating UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout; [layout invalidateLayout]; } 

然后我定义了这样的单元格

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { screenRect = [[UIScreen mainScreen] bounds]; screenWidth = screenRect.size.width; CGSize elementSize = CGSizeMake(screenWidth/screenDivide, 100); return elementSize; } 

我通过检测setBounds:方法中的方向更改来处理此问题。 我们UICollectionView并覆盖setBounds:方法(见下文)。 在flowLayoutForGallerySize我们使用不同的间距和itemSize创build一个新的UICollectionViewFlowLayout ,具体取决于集合视图的大小。

 - (void)setBounds:(CGRect)bounds { // detect orientation changes and update itemSize in the flow layout CGSize oldSize = self.bounds.size; [super setBounds:bounds]; BOOL wasLandscape = (oldSize.width > oldSize.height); BOOL nowLandscape = (bounds.size.width > bounds.size.height); if (wasLandscape != nowLandscape) { // create a new flow layout object for the new gallery size self.flowLayout = [self flowLayoutForGallerySize:bounds.size]; // change to the new flow layout [self setCollectionViewLayout:self.flowLayout animated:NO]; DLog(@"orientation change to %@", NSStringFromCGSize(bounds.size)); } }