I'm trying to use the built-in textLabel in a UITableViewHeaderFooterView in order display titles in the section headers of a UITableView.
These titles have an unknown amount of content and so need to cover multiple lines.
If this was a table cell then myCell.numberOfLines = 0 would work (along with estimatedHeightForRowAtIndexPath returning UITableViewAutomaticDimension). But I can't get anything similar to work with table headers.
I've tried setting textLabel.numberOfLines = 0 in viewForHeaderInSection and/or in willDisplayHeaderView. I've also tried setting it in a custom subclass I've created that the headers are using (set up with let sectionHeader = tableView.dequeueReusableHeaderFooterViewWithIdentifier("myIdentifier") as MyTableSectionHeaderSubclass). In that subclass I've tried setting textLabel.numberOfLines = 0 in the init function, as well as in layoutSubviews()
I've already set the correct height of each header by calculating the amount of space the text string will take up (using CGSizeMake in heightForHeaderInSection, can provide more info about this if it's of any help). So, there's enough vertical space for the labels to expand - they're just stuck on one line, with their text cut off and ending with an ellipsis.
I'm trying this approach in order to avoid using a custom UILabel to display the title. While I can apply multiline that way, this brings other problems such as label position/frame being lost when table rows are added or deleted.
Does anyone know if multi-line text is even possible with a UITableViewHeaderFooterView's built-in textLabel? Or is a custom UILabel my only option?
Many thanks!
I do think using a custom UILabel is a better approach as you can take control on all attributes.
First of all, a handy function to calculate the UILabel height. (Below is my version for my specific project). Notice that I set the NSMutableParagraphStyle which I think is the best way to handle line break, line spacing etc.
internal func heightForLabel(attributedString:NSMutableAttributedString, font:UIFont, width:CGFloat, lineSpacing: CGFloat) -> CGFloat{
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
let label:UILabel = UILabel(frame: CGRect(x:0, y:0, width:width, height:CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.font = font
label.textAlignment = .left
attributedString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
label.attributedText = attributedString
label.sizeToFit()
return label.frame.height
}
Then in your view controller, pre-calculate the section header heights
fileprivate let sectionHeaders = ["Header1", "Loooooooooooooooooooooong Header which occupies two lines"]
fileprivate var sectionHeaderHeights : [CGFloat] = []
override func viewDidLoad() {
super.viewDidLoad()
//Calculate the label height for each section headers, then plus top and down paddings if there is any. Store the value to `sectionHeaderHeights`
}
UITableViewDelegate methods
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return sectionHeaderHeights[section]
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let sectionHeader = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: sectionHeaderHeights[section]-paddings))
sectionHeader.backgroundColor = .clear
let sectionTitleLabel = UILabel()
sectionTitleLabel.text = sectionTitles[section]
sectionTitleLabel.font = UIFont(name: "GothamPro", size: 18)
sectionTitleLabel.textColor = .black
sectionTitleLabel.backgroundColor = .clear
sectionTitleLabel.frame = CGRect(x: padding, y: sectionHeader.frame.midY, width: sectionTitleLabel.frame.width, height: sectionTitleLabel.frame.height)
sectionHeader.addSubview(sectionTitleLabel)
return sectionHeader
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With