Swift iOS 9:确定纵向和横向收集视图的大小

Swift iOS 9:确定纵向和横向收集视图的大小,swift,uicollectionview,height,ios9,statusbar,Swift,Uicollectionview,Height,Ios9,Statusbar,我有一个简单的UICollectionViewController,它在UINavigationController中嵌入了FlowLayout 在UICollectionViewFlowDelegate中,我尝试根据屏幕上集合视图的实际可用大小计算单元格的大小 iOS 9上的标准行为似乎是,在纵向中,状态栏高20像素且可见,导航栏高44像素且可见。在横向视图中,状态栏是隐藏的,导航栏的高度为32px 问题是,当我试图根据这些数字计算单元格大小时,我在collectionView:sizeFor

我有一个简单的UICollectionViewController,它在UINavigationController中嵌入了FlowLayout

在UICollectionViewFlowDelegate中,我尝试根据屏幕上集合视图的实际可用大小计算单元格的大小

iOS 9上的标准行为似乎是,在纵向中,状态栏高20像素且可见,导航栏高44像素且可见。在横向视图中,状态栏是隐藏的,导航栏的高度为32px

问题是,当我试图根据这些数字计算单元格大小时,我在collectionView:sizeForItemAtIndexPath函数中得到了错误的数据

我将下面的代码放在这个函数中,以演示我得到的值

    print ("Device......: " + UIDevice.currentDevice().name)
    print ("Model.......: " + UIDevice.currentDevice().localizedModel)
    print ("Orientation.: " + String(UIDevice.currentDevice().orientation.rawValue))
    print ("View width..: " + String(self.view.bounds.size.width))
    print ("View height.: " + String(self.view.bounds.size.height))
    print ("S.bar height: " + String(UIApplication.sharedApplication().statusBarFrame.height))
    print ("S.bar hidden: " + String(UIApplication.sharedApplication().statusBarHidden))
    print ("N.bar height: " + String(self.navigationController?.navigationBar.frame.height))
当应用程序在iPhone 6模拟器上以纵向方式启动时,我得到以下输出:

Device......: iPhone Simulator
Model.......: iPhone
Orientation.: 1
View width..: 375.0
View height.: 603.0
S.bar height: 20.0
S.bar hidden: false
N.bar height: Optional(44.0)
到目前为止,一切都很好。然后,当我将设备旋转到横向时,我得到以下结果:

Device......: iPhone Simulator
Model.......: iPhone
Orientation.: 4
View width..: 667.0
View height.: 323.0
S.bar height: 20.0
S.bar hidden: false
N.bar height: Optional(32.0)
Device......: iPhone Simulator
Model.......: iPhone
Orientation.: 1
View width..: 375.0
View height.: 623.0
S.bar height: 0.0
S.bar hidden: true
N.bar height: Optional(44.0)
现在,视图高度与实际视图高度相差20px,状态栏的高度显示为20,而实际上为0。此外,状态栏显示为可见,而实际上是隐藏的。但它变得更加奇怪

当我将设备旋转回纵向时,我得到以下结果:

Device......: iPhone Simulator
Model.......: iPhone
Orientation.: 4
View width..: 667.0
View height.: 323.0
S.bar height: 20.0
S.bar hidden: false
N.bar height: Optional(32.0)
Device......: iPhone Simulator
Model.......: iPhone
Orientation.: 1
View width..: 375.0
View height.: 623.0
S.bar height: 0.0
S.bar hidden: true
N.bar height: Optional(44.0)
因此,状态栏高度的计算似乎有所延迟

现在的问题是如何计算函数中集合视图可见部分的大小

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

UIApplication.sharedApplication().statusBarHidden
在iOS 9中不推荐使用

编辑#1:


在iPhone6plus和6splus模拟器上,我似乎得到了预期的值。4s、5、6和6s给出问题中显示的值。

为什么不直接访问UICollectionView框架属性

在这种方法中

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
只需访问
collectionview.frame
并根据它计算大小


千万不要依赖硬编码的高度值,因为在新版iOS中,这些值可能会发生变化。

为什么不直接访问UICollectionView框架属性

在这种方法中

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
只需访问
collectionview.frame
并根据它计算大小

千万不要依赖硬编码的高度值,因为在新版iOS中,这些值可能会发生变化。

您需要使用:

dispatch_async(dispatch_get_main_queue()) 
   { 
      println("height :(view.bounds.size.height)") 
      println("width :(view.frame.size.width)") 
     // all other code depends on UIDevice.current.orientation 
    }
此代码将在轮换完成(在主队列中)且新尺寸可用后执行

您需要使用:

dispatch_async(dispatch_get_main_queue()) 
   { 
      println("height :(view.bounds.size.height)") 
      println("width :(view.frame.size.width)") 
     // all other code depends on UIDevice.current.orientation 
    }

此代码将在轮换完成(在主队列中)且新尺寸可用后执行

不作为
collectionView.frame.height运行
返回与
self.view.bounds.size.height相同(错误)的值
。另外,问题的关键是避免硬编码值。这就是为什么我首先尝试计算大小。布局完成后是否重新加载数据?不,我没有。重新加载
didRotateFromInterfaceOrientation
成功了。谢谢另一方面需要注意的是:如果我不在willRotateToInterfaceOrientation中重新加载数据,那么会出现非常难看的过渡视觉效果。我非常感谢您的帮助!再次感谢。尽管如此,我还是将这个问题留到现在,因为操作系统实际上要求轮换一个新的单元大小。由于状态栏的值处于关闭状态,因此无法正确计算。重新加载数据只会触发第二次重新计算,据我目前的理解,这是不必要的。如果不想重新加载UICollectionView,可以调用
invalidateLayout
。它将只重新加载布局,而不加载模型。不作为
collectionView.frame.height
工作,返回与
self.view.bounds.size.height相同(错误)的值。另外,问题的关键是避免硬编码值。这就是为什么我首先尝试计算大小。布局完成后是否重新加载数据?不,我没有。重新加载
didRotateFromInterfaceOrientation
成功了。谢谢另一方面需要注意的是:如果我不在willRotateToInterfaceOrientation中重新加载数据,那么会出现非常难看的过渡视觉效果。我非常感谢您的帮助!再次感谢。尽管如此,我还是将这个问题留到现在,因为操作系统实际上要求轮换一个新的单元大小。由于状态栏的值处于关闭状态,因此无法正确计算。重新加载数据只会触发第二次重新计算,据我目前的理解,这是不必要的。如果不想重新加载UICollectionView,可以调用
invalidateLayout
。它只会重新加载布局,而不会重新加载模型。您需要使用:dispatch_async(dispatch_get_main_queue()){println(“height:(view.bounds.size.height)”)println(“width:(view.frame.size.width)”//所有其他代码取决于UIDevice.current.orientation。此代码将在旋转完成后(在主队列中)执行您需要使用:dispatch_async(dispatch_get_main_queue()){println(“height:(view.bounds.size.height)”)println(“width:(view.frame.size.width)”//所有其他代码取决于UIDevice.current.orientation此代码将在旋转完成后执行(在主队列中)新的尺寸也有。