在方向更改时管理集合视图单元格布局的正确方法

Proper way to manage collection view cell layout on orientation change

我的 UICollectionView 上几乎没有单元格,并且在旋转时行数和列数会发生变化。我可以通过以下方式实现这一目标:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
    if UIDevice.currentDevice().orientation.isPortrait.boolValue{
        return CGSizeMake((collectionView.frame.size.width-2)/2, (collectionView.frame.size.height - 4)/3)
    }
    else{
        return CGSizeMake((collectionView.frame.size.width-4)/3, (collectionView.frame.size.height - 4)/3)
    }
}

在设备旋转之前一切都很好。为了轮换,我重新加载了这样的集合视图

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
    myCollectionView!.reloadData()
}

最终结果看起来像 this。(抱歉 gif 不好)

已达到所需的单元格数量。但是正如您从 link 中看到的那样,在旋转发生时,有一小段时间会注意到间隙。这种效果是不希望的。一次又一次地重新加载 UICollectionView 只是为了修复布局也是不好的。我能够实现我想要的,但不是以正确的方式。一些专家的想法将不胜感激。

假设您有 UICollectionViewFlowLayout,这是一个解决方案:

首先,将此添加到您的 ViewController:

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ResultsCollectionViewController.orientationDidChange(_:)), name: UIDeviceOrientationDidChangeNotification, object: nil)

不要忘记在 VC 关闭时删除自身:

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

然后实现选择器方法:

func orientationDidChange(notification: NSNotification) {
    collectionView!.collectionViewLayout.invalidateLayout()
}

基本上你只是在设备方向改变时发送一个通知,然后选择器使你的布局无效以便它被刷新。

编辑:

这是一个基本的 UICollectionViewFlowLayout 设置方法:

func setupCollectionViewLayout(minimumInteritemSpacing minimumInteritemSpacing: CGFloat, minimumLineSpacing: CGFloat) {
    let layout = UICollectionViewFlowLayout()
    layout.minimumInteritemSpacing = minimumInteritemSpacing
    layout.minimumLineSpacing = minimumLineSpacing
    collectionView?.collectionViewLayout = layout
}

然后在 viewDidLoad 中你可以调用:

// Setup a layout
setupCollectionViewLayout(minimumInteritemSpacing: 0, minimumLineSpacing: 0)

如果您想使用 UICollectionViewDelegateFlowLayout,您可以使用以下模板,但请记住您必须对其进行调整!

// ----------------------------------------------------------------------------------
// MARK: - UICollectionViewDelegateFlowLayout
// ----------------------------------------------------------------------------------

extension ResultsCollectionViewController: UICollectionViewDelegateFlowLayout {

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

    switch UIDevice.currentDevice().userInterfaceIdiom {
    case .Phone:
        return CGSize(width: self.view.frame.width, height: 100.0)
    case .Pad:
        return CGSize(width: self.view.frame.width/2.0, height: 100.0)
    default:
        return CGSize(width: self.view.frame.width, height: 100.0)
    }


}

}