如何在旋转时定义CollectionView的大小

Rob*_*arr 41 xcode objective-c ios uicollectionview

我有一个带有2个CollectionView控制器的viewcontroller.

我想轮换时只有一个集合视图调整为自定义大小而另一个保持不变.

我试过用:

- (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);
}
Run Code Online (Sandbox Code Playgroud)

但是,这只会改变两个集合视图.如何让它仅针对一个集合?

Oli*_*son 65

继承人我的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
}
Run Code Online (Sandbox Code Playgroud)

编辑:使用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()
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*Bąk 49

使用自iOS 8以来的新API 我正在使用:

斯威夫特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()
    }
}
Run Code Online (Sandbox Code Playgroud)

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];
}
Run Code Online (Sandbox Code Playgroud)


Nei*_*tha 14

验证的答案不高效

问题 - 在viewWillLayoutSubviews()中使布局无效是一项繁重的工作. 实例化ViewController时,会多次调用viewWillLayoutSubviews().

我的解决方案(Swift) - 在UICollectionViewDelegateFlowLayout中嵌入您的大小操作.

// 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)
}
Run Code Online (Sandbox Code Playgroud)

  • 你需要做的就是调用self.collectionView!.collectionViewLayout.invalidateLayout()然后在sizeForItemAtIndexPath中,只需从view/collectionView中获取新的边界,而不是保存大小并调用performBatchUpdates. (6认同)