在方向更改时管理集合视图单元格布局的正确方法
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)
}
}
}
我的 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)
}
}
}