如何在 tableHeaderView 中放置动态多行 UILabel
How to place a dynamic multiline UILabel in tableHeaderView
我创建了一个链接到名为 InstructionView 的 UIView class 的 xib 视图。该视图只包含一个 UILabel,它被限制在所有边上。
标签行数为0,换行设置为自动换行
然后将此视图添加到 stackView。然后那个 stackView 被设置为 tableView 的 tableHeaderView。
override func viewsToAddAfterTitle() -> [UIView] {
var views: [UIView] = []
if let view = Bundle.main.loadNibNamed(Constants.Nibs.instructionView, owner: self, options: nil)?.first as? InstructionView {
view.fillWithInstruction("A long text that needs more than 1 line")
views.append(view)
view.setNeedsLayout()
view.layoutIfNeeded()
}
return views
}
func addTableHeaderView() {
if let viewHeader: ViewHeader = Bundle.main.loadNibNamed(Constants.Nibs.viewHeader, owner: self, options: nil)?.first as? ViewHeader {
viewHeader.setTitle(titleText: headerTitle())
var arrangedStackSubviews: [UIView] = viewsToAddBeforeTitle()
arrangedStackSubviews.append(viewHeader)
arrangedStackSubviews.append(contentsOf: viewsToAddAfterTitle())
let stack = UIStackView(arrangedSubviews: arrangedStackSubviews)
stack.distribution = .fill
stack.axis = NSLayoutConstraint.Axis.vertical
stack.alignment = .fill
stack.autoresizingMask = [.flexibleWidth, .flexibleHeight]
tableView.tableHeaderView = stack
}
}
加载笔尖时调用 fillWithInstruction 函数。我调用它来设置标签的文本。
func fillWithInstruction(_ instruction: String) {
instructionLabel.text = instruction
instructionLabel.sizeToFit()
}
我尝试计算 intrinsicContentSize 并基于此设置标签高度的限制。我尝试将标签放在视图 and/or 堆栈中。
我试过的 None 有效。如果该文本需要多于 1 行,我希望标签显示多于 1 行。但目前它总是显示 1 行。
创建一个 UITableViewHeaderFooterView 并将其与 viewForHeaderInSection 委托一起使用。
看看这个例子
好的,这是真正的交易:
创建此扩展:
extension String {
func heightNeededForLabel(_ label: UILabel) -> CGFloat {
let width = label.frame.size.width
guard let font = label.font else {return 0}
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedString.Key.font: font], context: nil)
return boundingBox.height + 20
}
}
+20只是为了给它多一些space
并这样称呼它:
func fillWithInstruction(_ instruction: String) {
instructionLabel.text = instruction
guard let instructionLabel = instructionLabel else {return}
instructionLabel.addConstraint(NSLayoutConstraint(item: instructionLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 2, constant: instruction.heightNeededForLabel(instructionLabel)))
}
标签行数为0,换行设置为自动换行
然后将此视图添加到 stackView。然后那个 stackView 被设置为 tableView 的 tableHeaderView。
override func viewsToAddAfterTitle() -> [UIView] {
var views: [UIView] = []
if let view = Bundle.main.loadNibNamed(Constants.Nibs.instructionView, owner: self, options: nil)?.first as? InstructionView {
view.fillWithInstruction("A long text that needs more than 1 line")
views.append(view)
view.setNeedsLayout()
view.layoutIfNeeded()
}
return views
}
func addTableHeaderView() {
if let viewHeader: ViewHeader = Bundle.main.loadNibNamed(Constants.Nibs.viewHeader, owner: self, options: nil)?.first as? ViewHeader {
viewHeader.setTitle(titleText: headerTitle())
var arrangedStackSubviews: [UIView] = viewsToAddBeforeTitle()
arrangedStackSubviews.append(viewHeader)
arrangedStackSubviews.append(contentsOf: viewsToAddAfterTitle())
let stack = UIStackView(arrangedSubviews: arrangedStackSubviews)
stack.distribution = .fill
stack.axis = NSLayoutConstraint.Axis.vertical
stack.alignment = .fill
stack.autoresizingMask = [.flexibleWidth, .flexibleHeight]
tableView.tableHeaderView = stack
}
}
加载笔尖时调用 fillWithInstruction 函数。我调用它来设置标签的文本。
func fillWithInstruction(_ instruction: String) {
instructionLabel.text = instruction
instructionLabel.sizeToFit()
}
我尝试计算 intrinsicContentSize 并基于此设置标签高度的限制。我尝试将标签放在视图 and/or 堆栈中。
我试过的None 有效。如果该文本需要多于 1 行,我希望标签显示多于 1 行。但目前它总是显示 1 行。
创建一个 UITableViewHeaderFooterView 并将其与 viewForHeaderInSection 委托一起使用。
看看这个例子
好的,这是真正的交易:
创建此扩展:
extension String {
func heightNeededForLabel(_ label: UILabel) -> CGFloat {
let width = label.frame.size.width
guard let font = label.font else {return 0}
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedString.Key.font: font], context: nil)
return boundingBox.height + 20
}
}
+20只是为了给它多一些space
并这样称呼它:
func fillWithInstruction(_ instruction: String) {
instructionLabel.text = instruction
guard let instructionLabel = instructionLabel else {return}
instructionLabel.addConstraint(NSLayoutConstraint(item: instructionLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 2, constant: instruction.heightNeededForLabel(instructionLabel)))
}