接受的答案实际上并没有回答问题。相反,它通过使用 SECTION 标头提供了替代方案。其他人已经回答了这个问题,但我将在此处复制答案并提供更多说明。
加载视图
表格视图与 iPhone 一样古老,因此有时您必须强制它执行您想要的操作。
首先我们需要加载标题并手动设置它的高度。否则视图会占用比它需要的更多的高度。我们在 viewDidLayoutSubviews 回调上执行此操作:
lazy var profileHeaderView: ProfileHeaderView = {
let headerView = ProfileHeaderView()
return headerView
}()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
sizeHeaderToFit()
}
private func sizeHeaderToFit() {
profileHeaderView.setNeedsLayout()
profileHeaderView.layoutIfNeeded()
var frame = profileHeaderView.frame
frame.size.height = profileHeaderView.calculateHeight()
profileHeaderView.frame = frame
tableView.tableHeaderView = profileHeaderView
}
如您所见,我喜欢将视图放在惰性变量中。这可确保它们始终被创建,但仅在我开始使用它们时才创建。
您还可以看到我正在计算高度。在某些情况下,您的高度是固定的,因此您只需将帧高度设置为硬编码值。
设置一些优先级
我们可能会在调试器中看到一些约束警告。发生这种情况是因为表格视图在使用我们上面指定的大小之前首先强制为 0x0 大小。此时,您的约束和视图的高度相互冲突。
要清除这些,我们只需设置约束优先级。首先,您应该将标题视图组件包装在另一个视图中(我通常总是为标题视图这样做)。这将使您在标题视图上更轻松地管理约束。
然后我们需要将底部约束优先级设置为高:
containerView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
containerView.setContentHuggingPriority(.defaultHigh, for: .vertical)
这是一个更完整的例子:
警告:认为它仍可用作布置视图的指南,如果您使用 nib 或情节提要创建视图,请不要使用此代码。
class ProfileHeaderView: UIView {
lazy var containerView: UIView = {
let view = UIView()
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupLayout()
}
required init?(coder aDecoder: NSCoder) {
// We do this because the view is not created using storyboards or nibs.
fatalError("init(coder:) has not been implemented")
}
private func setupLayout() {
self.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
containerView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
containerView.setContentHuggingPriority(.defaultHigh, for: .vertical)
// Set the rest of your constraints against your containerView not self and add your subviews to your containerView not self
}
}
以下是使用 snap-kit 设置约束的示例:
containerView.snp.makeConstraints() { make in
make.top.equalTo(self.snp.top)
make.leading.equalTo(self.snp.leading)
make.trailing.equalTo(self.snp.trailing)
make.bottom.equalTo(self.snp.bottom).priority(.high)
}
确保将约束添加到 containerView 而不是 self 并使用 containerView 添加子视图和其余约束。