Reputation: 1614
I have a UILabel
in a stackview in a content view that is in a tableview cell. Everything is working correctly and the cell is resizing but i cannot center the text in the UILabel
. I always have strange spaces in the bottom of the text. Check out screen shot.
Yellow: content view Green: stackview Blue: label
Additional info: No static height for cells. The yellow view has top bottom and trailing and leading constraints plus horizontal and vertical aligned to super view same thing the stack view. The only thing that has constant height which I activate and deactivate through code is the button. So it hides and shows according to the cell. Stackview is fill proportionally.
The UILabel
is sizeToFit
Also tried:
detailLbl.textAlignment = .center
detailLbl.lineBreakMode = .byWordWrapping //also tried byClipping
detailLbl.baselineAdjustment = .alignCenters
The text inside i parse as HTML
"<p><font color=\"#cd1719\">V/. </font>…The Word of the Lord.<br><b></b><font color=\"#cd1719\">R/. </font><b>Thanks be to God.</b></p>"
Second screenshot
"<h6 lang=\"en\" style=\"color=#cd1719 !important; font-weight: normal !important\"><font color=\"#cd1719\" weight=\"normal\"><i>The alleluia is said or sung.</i></font></h6>"
This is an NSAttributedString
extension I use for parsing HTML
extension NSAttributedString {
convenience init(htmlString html: String, font: UIFont? = nil, useDocumentFontSize: Bool = true) throws {
let options: [NSAttributedString.DocumentReadingOptionKey : Any] = [
.documentType: NSAttributedString.DocumentType.html,
.characterEncoding: String.Encoding.utf8.rawValue
]
let data = html.data(using: .utf8, allowLossyConversion: true)
guard (data != nil), let fontFamily = font?.familyName, let attr = try? NSMutableAttributedString(data: data!, options: options, documentAttributes: nil) else {
try self.init(data: data ?? Data(html.utf8), options: options, documentAttributes: nil)
return
}
let fontSize: CGFloat? = useDocumentFontSize ? nil : font!.pointSize
let range = NSRange(location: 0, length: attr.length)
attr.enumerateAttribute(.font, in: range, options: .longestEffectiveRangeNotRequired) { attrib, range, _ in
if let htmlFont = attrib as? UIFont {
let traits = htmlFont.fontDescriptor.symbolicTraits
var descrip = htmlFont.fontDescriptor.withFamily(fontFamily)
if (traits.rawValue & UIFontDescriptor.SymbolicTraits.traitBold.rawValue) != 0 {
descrip = descrip.withSymbolicTraits(.traitBold)!
}
if (traits.rawValue & UIFontDescriptor.SymbolicTraits.traitItalic.rawValue) != 0 {
descrip = descrip.withSymbolicTraits(.traitItalic)!
}
attr.addAttribute(.font, value: UIFont(descriptor: descrip, size: fontSize ?? htmlFont.pointSize), range: range)
}
}
self.init(attributedString: attr)
}
}
And this is how I use it in the code
if let attributedString = try? NSAttributedString(htmlString: htmlTxt, font: UIFont(name: "Avenir-Roman", size: CGFloat(Constants.defualtContentDescriptionFontSize)), useDocumentFontSize: false) {
cell.detailLbl.attributedText = attributedString
}
Upvotes: 0
Views: 391
Reputation: 77647
Part of the problem is that you are using formatted html text, which includes the "extra space."
For example, your first html text line includes <p> </p>
tags.
This code creates two green-background labels, each the same width, each with no height constraint:
class ViewController: UIViewController, UIScrollViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let firstLabel = UILabel()
firstLabel.backgroundColor = .green
firstLabel.numberOfLines = 0
firstLabel.translatesAutoresizingMaskIntoConstraints = false
let secondLabel = UILabel()
secondLabel.backgroundColor = .green
secondLabel.numberOfLines = 0
secondLabel.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(firstLabel)
view.addSubview(secondLabel)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// first label 40-pts from top, 20-pts on each side
firstLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
firstLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
firstLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
// second label 40-pts from bottom of first label, 20-pts on each side
secondLabel.topAnchor.constraint(equalTo: firstLabel.bottomAnchor, constant: 40.0),
secondLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
secondLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
])
var htmlTxt = "<p><font color=\"#cd1719\">V/. </font>…The Word of the Lord.<br><b></b><font color=\"#cd1719\">R/. </font><b>Thanks be to God.</b></p>"
if let attributedString = try? NSAttributedString(htmlString: htmlTxt, font: UIFont(name: "Avenir-Roman", size: 24.0), useDocumentFontSize: false) {
firstLabel.attributedText = attributedString
//cell.detailLbl.attributedText = attributedString
}
htmlTxt = "<font color=\"#cd1719\">V/. </font>…The Word of the Lord.<br><b></b><font color=\"#cd1719\">R/. </font><b>Thanks be to God.</b>"
if let attributedString = try? NSAttributedString(htmlString: htmlTxt, font: UIFont(name: "Avenir-Roman", size: 24.0), useDocumentFontSize: false) {
secondLabel.attributedText = attributedString
//cell.detailLbl.attributedText = attributedString
}
}
}
The output:
The difference between the two? For the second label, I removed the <p> </p>
tags before processing the html with your extension.
Your second html text defines it as h6
... here's the output with that string:
Again, the difference between the two is that I removed the h6
tag before processing the html.
You'll probably need to modify your extension to remove the paragraph tags, or set a paragraph style that would ignore them.
Upvotes: 1