xcode 创建 UICollectionViewCell 时子视图框架不正确

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28269452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 06:35:22  来源:igfitidea点击:

Subview frame is incorrect when creating UICollectionViewCell

iosxcodeswiftuicollectionviewuicollectionviewcell

提问by Felipe Ferri

The problem

问题

I created a UICollectionViewController with a custom UICollectionViewCell. The custom cell contains a large and rectangular UIView (named colorView) and a UILabel (named nameLabel).

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

When the collection is first populated with its cells and I print colorView.frame, the printed frames have incorrect values. I know they are incorrect, because the colorView frames are larger than the cell frame themselves, even though the colorView gets drawn correctly.

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

However, if I scroll the collectionView enough to trigger a reuse of a previously created cell, the colorView.frame now has correct values! I need the correct frames because I want to apply rounded corners to the colorView layer and I need the correct coloView size in order to do this. By the way, in case you are wondering, colorView.bounds also has the same wrong size value as the colorView.frame.

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

The question

问题

Why are the frames incorrect when creating the cells?

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

And now some code

现在一些代码

This is my UICollectionViewCell:

这是我的 UICollectionViewCell:

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

and this is the UICollectionViewController:

这是 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)
    }
}

The collection view is setup in order to show two cells at a time, vertically, each cell containing a large rectangle painted with a color and a label with the color name.

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

When I just run the above code on the simulator, I get the following printed result:

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

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)

It is a weird result - colorView.frame has a height of 568 points, while the cell frame is only 333.5 points tall.

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

If I drag the collectionView down and a cell gets reused, the following result is printed:

如果我向下拖动 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)

Something, which I can't understand, happened along the way that corrects the frame of colorView.

在纠正colorView框架的过程中发生了一些我无法理解的事情。

I think it has something to do with the fact that the cell is loaded from the Nib, so instead of using the init(frame: frame) initializer the controller uses the init(coder: aCoder) initializer, so as soon as the cell is created it probably comes with some default frame which I can't edit anyhow.

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

I'll appreciate any help that allows me to understand what is happening!

我将不胜感激任何让我了解正在发生的事情的帮助!

I am using Xcode 6.1.1. with the iOS SDK 8.1.

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

回答by Jon Vogel

You can get the final frames of your cell by overriding layoutIfNeeded() in your custom Cell class like this:

您可以通过在自定义 Cell 类中覆盖 layoutIfNeeded() 来获取单元格的最终帧,如下所示:

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

then in your UICollectionView data Source method cellForRowAtIndexPath: do this:

然后在您的 UICollectionView 数据源方法 cellForRowAtIndexPath 中:执行以下操作:

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

回答by RyanG

I had the same issue with a UICollectionViewCellusing auto layout constraints.

我在UICollectionViewCell使用自动布局约束时遇到了同样的问题。

I had to call layoutIfNeededbefore I was configuring my subview that relied on the views frame width.

layoutIfNeeded在配置依赖于视图框架宽度的子视图之前,我不得不调用。

回答by Vadim Bulavin

Had this issue with Core Graphics drawing in iOS 10, Swift 3.0.1.

iOS 10, Swift 3.0.1 中使用 Core Graphics 绘图存在此问题。

Add this method to UICollectionViewsubclass:

将此方法添加到UICollectionView子类中:

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

My problem was that Core Graphics shapes were not calculated properly, because a layoutSubviews()wasn't called.

我的问题是 Core Graphics 形状没有正确计算,因为layoutSubviews()没有调用 a 。

回答by Felipe Ferri

Ok, I understand now that the cell is created before auto layout defines its frames. That is the reason why at the moment of creation the bounds are wrong. When the cells are reused the frames have been already corrected.

好的,我现在明白单元格是在自动布局定义其框架之前创建的。这就是为什么在创造的那一刻界限是错误的。当单元被重新使用时,帧已经被校正。

I was having this problem while creating a custom UIView that placed some layers and subviews in specific coordinates. When instances of this UIView were created, the placement of the subviews were all wrong (because auto layout hadn't kick off yet).

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

I found out that instead of configuring the view subviews on init(coder: aCoder)I had to override the method layoutSubviews(). This is called when auto layout asks each view to layout its own subviews, so at this point at least the parent view has the correct frame and I can use it for laying the subviews correctly.

我发现init(coder: aCoder)我必须覆盖方法而不是配置视图子视图layoutSubviews()。当自动布局要求每个视图布局自己的子视图时会调用它,因此此时至少父视图具有正确的框架,我可以使用它来正确放置子视图。

Probably if I had used constraints on the custom view code instead of dealing myself with frame sizes and positioning then the layout would have been done properly and it wouldn't be necessary to override layoutSubviews().

可能如果我在自定义视图代码上使用约束而不是处理框架大小和定位,那么布局就会正确完成并且不需要覆盖layoutSubviews().