创buildUICollectionViewCell时,子视图框架不正确

问题

我用自定义的UICollectionViewCell创build了一个UICollectionViewController。 自定义单元格包含一个大的矩形UIView(名为colorView)和一个UILabel(名为nameLabel)。

当该集合首先填充其单元格并打印colorView.frame时,打印的框架具有不正确的值。 我知道他们是不正确的,因为colorView框架比单元格框架本身大,即使colorView得到正确。

但是,如果我滚动collectionView足以触发以前创build的单元格的重用,colorView.frame现在具有正确的值! 我需要正确的框架,因为我想要应用圆angular到colorView图层,我需要正确的coloView大小,以便做到这一点。 顺便说一句,如果你想知道,colorView.bounds也有相同的错误大小值colorView.frame。

这个问题

为什么创build单元格时框架不正确?

现在有一些代码

这是我的UICollectionViewCell:

class BugCollectionViewCell: UICollectionViewCell { @IBOutlet weak var colorView: UIView! @IBOutlet weak var nameLabel: UILabel! } 

这是UICollectionViewController:

 import UIKit let reuseIdentifier = "Cell" let colors = [UIColor.redColor(), UIColor.blueColor(), UIColor.greenColor(), UIColor.purpleColor()] let labels = ["red", "blue", "green", "purple"] class BugCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { return 1 } override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return colors.count } override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as BugCollectionViewCell println("ColorView frame: \(cell.colorView.frame) Cell frame: \(cell.frame)") cell.colorView.backgroundColor = colors[indexPath.row] cell.nameLabel.text = labels[indexPath.row] return cell } func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { let width = self.collectionView?.frame.width let height = self.collectionView?.frame.height return CGSizeMake(width!, height!/2) } } 

集合视图的设置是为了一次显示两个单元格,垂直方向,每个单元格包含一个用颜色绘制的大矩形和一个带有颜色名称的标签。

当我在模拟器上运行上面的代码时,我得到以下打印结果:

 ColorView frame: (0.0,0.0,320.0,568.0) Cell frame: (0.0,0.0,375.0,333.5) ColorView frame: (0.0,0.0,320.0,568.0) Cell frame: (0.0,343.5,375.0,333.5) 

这是一个奇怪的结果 – colorView.frame有568点的高度,而单元格框架只有333.5点高。

如果我拖动collectionView并重新使用一个单元格,将打印以下结果:

 ColorView frame: (8.0,8.0,359.0,294.0) Cell frame: (0.0,1030.5,375.0,333.5) ColorView frame: (8.0,8.0,359.0,294.0) Cell frame: (0.0,343.5,375.0,333.5) 

有些东西,我不明白,沿着纠正colorView框架的方式发生。

我认为这与单元是从Nib加载的事实有关,所以不是使用init(frame:frame)初始化程序,而是使用init(coder:aCoder)初始化程序,因此一旦单元格创build它可能带有一些默认的框架,我无法编辑。

我会感谢任何帮助,让我明白发生了什么!

我正在使用Xcode 6.1.1。 与iOS SDK 8.1。

您可以通过在您的自定义Cell类中重写layoutIfNeeded()来获得单元格的最终框架,如下所示:

 override func layoutIfNeeded() { super.layoutIfNeeded() self.subView.layer.cornerRadius = self.subView.bounds.width / 2 } 

那么在你的UICollectionView数据源方法cellForRowAtIndexPath中:做到这一点:

 let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! CustomCollectionViewCell cell.setNeedsLayout() cell.layoutIfNeeded() 

我使用自动布局约束与UICollectionViewCell有同样的问题。

在configuration依赖视图帧宽度的子视图之前,我不得不调用layoutIfNeeded

好吧,我现在明白,单元格是在自动布局定义帧之前创build的。 这就是为什么在创造这个界限时是错误的。 当单元重新使用时,帧已经被纠正。

我在创build自定义的UIView的时候遇到了这个问题,它在特定的坐标中放置了一些图层和子视图。 当创build这个UIView的实例时,子视图的位置都是错误的(因为自动布局还没有启动)。

我发现,而不是在init(coder: aCoder)上configuration视图子视图,我不得不重写方法layoutSubviews() 。 这是自动布局要求每个视图布局自己的子视图时调用的,所以在这一点上,至less父视图有正确的框架,我可以用它来正确铺设子视图。

也许如果我在自定义视图代码上使用了约束而不是自己处理框架的大小和位置,那么布局将会被正确地完成,并且不需要重写layoutSubviews()

有这个问题与核心graphics在iOS 10,Swift 3.0.1绘图。

这是一个帮助我的方法:

 override func didMoveToSuperview() { super.didMoveToSuperview() setNeedsLayout() layoutIfNeeded() } 

我的问题是核心graphics形状计算不正确,因为layoutSubviews()没有被调用。