5

I'm trying to implement by-design labels coming from Sketch e.g. I need text styles with font size = 19 and line height = 50. So I ended up using NSAttributedString with NSMutableParagraphStyle but was stopped by problem with text being sticked to bottom of UILabel

I've already tried to use lineHeightMultiple and lineSpacing but those didn't give me the line height I wanted so I ended up using minimumLineHeight and maximumLineHeight equal the same

Here is my approach to make NSAttributedString

    private static func makeAttributedString(
        with attributes: TextAttributes,
        text: String? = nil,
        alignment: NSTextAlignment = .center
    ) -> NSAttributedString {
        let font = UIFont(name: attributes.font.rawValue, size: attributes.fontSize)!

        let paragraph = NSMutableParagraphStyle()
        paragraph.alignment = alignment
        paragraph.paragraphSpacing = attributes.paragraph
        paragraph.minimumLineHeight = attributes.lineHeight // equal 50 in my case
        paragraph.maximumLineHeight = attributes.lineHeight // equal 50 in my case

        let attributes: [NSAttributedStringKey: Any] = [
            NSAttributedStringKey.paragraphStyle: paragraph,
            NSAttributedStringKey.foregroundColor: attributes.textColor,
            NSAttributedStringKey.kern: attributes.kern,
            NSAttributedStringKey.font: font
        ]

        return NSAttributedString(string: text ?? "", attributes: attributes)
    }

I expect result similar to design

but actually getting

Note: setting height constraint to 50 is not applicable because I also need multiline labels but there is the same bug with them

hh3n7a1
  • 91
  • 8

1 Answers1

3

Seems like I've found some workaround myself, maybe it will help someone.

The method is about setting baselineOffset like this:

NSAttributedStringKey.baselineOffset: (attributes.lineHeight - font.lineHeight) / 4

Works like charm:

https://i.stack.imgur.com/KS6k0.png

hh3n7a1
  • 91
  • 8
  • 1
    In addition to my previous question, I found a better solution, you just need to override UILabels `drawText(in rect: CGRect)` function, modify `rect` parameter `origin.y` and call `super.drawText(in rect: CGRect)` with your modified `rect` – hh3n7a1 Oct 05 '20 at 15:27
  • can you explain more? or give an example – Sajjad Apr 04 '23 at 12:34