IB 中的 Xib 尺寸影响最终视图

Xib dimensions in IB affects final view

我遇到了与此类似的问题:

但我的是一个 TableView 单元格,所以我无法访问 viewDidLayoutSubviews(),这就是该问题的解决方式。我尝试覆盖单元格的 layoutSubviews() 但它仍然不正确。

布局只是一个集合视图,具有 table 视图单元格的前导、尾随、顶部和底部约束。集合视图也有一个高度限制,我用它来更新单元格大小。如果我打印 collectionView 高度,我可以看到它是错误的,但它的错误程度根据 xib 而变化。

我也尝试过向单元格添加自定义滑块视图,但滑块的大小也不正确,直到我与它交互,此时它会自行纠正。 slider 的初始尺寸显然是根据xib 的宽度

我还将 table 视图的 sizeForRow 设置为 automaticDimension,并设置了估计的行大小。

有什么想法吗?

首先,如果 XIB 设置、编码和加载正确,Interface Builder (IB) 中 XIB 的大小不会 在 运行 时影响视图的大小。

这是一个快速、简单的示例...

对于带有 UIView 的 table 视图单元格 XIB(我们将向其添加阴影和圆角)和 UILabel 子视图,我们是否调整单元格的大小在 IB 的 XIB 中是这样的:

或者像这样:

或者像这样:

使用此代码:

DemoTableViewCell

class DemoTableViewCell: UITableViewCell {
    @IBOutlet var label: UILabel!
    @IBOutlet var myView: UIView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        myView.layer.cornerRadius = 8
        myView.layer.shadowOffset = CGSize(width: 0, height: 3)
        myView.layer.shadowRadius = 3
        myView.layer.shadowOpacity = 0.5
    }
}

DemoTableViewController

class DemoTableViewController: UITableViewController {

    let myData: [String] = [
        "Single Line",
        "A longer string which will wrap in Portrait Orientation",
        "This string is long enough that the text will need to word-wrap (on an iPhone 8) whether in Portrait Orientation or Landscape Orientation",
        "Another Single Line",
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "Demo Table"
        view.backgroundColor = .systemBackground
        tableView.register(UINib(nibName: "DemoTableViewCell", bundle: nil), forCellReuseIdentifier: "c")
        tableView.tableFooterView = UIView()
        tableView.separatorStyle = .none
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myData.count
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "c", for: indexPath) as! DemoTableViewCell
        cell.label.text = myData[indexPath.row]
        return cell
    }

}

在 运行 时,我们将得到:

并注意当视图大小改变时布局会自动处理:


那么,您的设计存在一些问题...

首先,尝试以这种方式使用 UICollectionView 本质上是有问题的。集合视图旨在布局它们的单元格,并在单元格多于将容纳的单元格时滚动

通过使用相反的方法 - 获取显示所有单元格所需的大小,然后调整集合视图的大小,同时 将其嵌入 table 视图单元格中 - 是一项相当复杂的任务。

为了集合视图确定其contentSize.height:

  • 需要给它一个宽度
  • 它需要获取单元格部分和项目计数
  • 它需要获取单元格的大小(特别是如果它们不是固定大小)
  • 然后需要对单元格进行布局
  • 并且... 这是一个异步进程
  • and... 在这种情况下,集合视图在 table 视图布局其单元格之前不会获得其宽度

尝试处理所有这些的时间非常困难。

现在,由于您放弃了集合视图的许多好处(滚动、单元格重用等),并且您可能会使用少量的“项目”(如果您试图用几百个单元格来做这个你可能需要重新考虑你的 UI 设计)你几乎肯定最好自己编写代码来布局视图。


有关更多细节和代码示例,我在此处提供了一个演示项目:https://github.com/DonMag/TagsTableExample