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
我遇到了与此类似的问题:
但我的是一个 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