How to control the line spacing in UILabel

260,717

Solution 1

I thought about adding something new to this answer, so I don't feel as bad... Here is a Swift answer:

import Cocoa

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 40

let attrString = NSMutableAttributedString(string: "Swift Answer")
attrString.addAttribute(.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length))

var tableViewCell = NSTableCellView()
tableViewCell.textField.attributedStringValue = attrString

"Short answer: you can't. To change the spacing between lines of text, you will have to subclass UILabel and roll your own drawTextInRect, or create multiple labels."

See: Set UILabel line spacing


This is a really old answer, and other have already addded the new and better way to handle this.. Please see the up to date answers provided below.

Solution 2

In Xcode 6 you can do this in the storyboard:

enter image description here

Solution 3

Starting from iOS 6 you can set an attributed string to the UILabel. Check the following :

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:label.text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = spacing;
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, label.text.length)];

label.attributedText = attributedString;

Solution 4

The solutions stated here didn't work for me. I found a slightly different way to do it with the iOS 6 NSAttributeString:

myLabel.numberOfLines = 0; 
NSString* string = @"String with line one. \n Line two. \n Line three.";
NSMutableParagraphStyle *style  = [[NSMutableParagraphStyle alloc] init];
style.minimumLineHeight = 30.f;
style.maximumLineHeight = 30.f;
NSDictionary *attributtes = @{NSParagraphStyleAttributeName : style,};
myLabel.attributedText = [[NSAttributedString alloc] initWithString:string
                                                         attributes:attributtes];   
[myLabel sizeToFit];

Solution 5

From Interface Builder (Storyboard/XIB):

enter image description here

Programmatically:

SWift 4

Using label extension

extension UILabel {

    // Pass value for any one of both parameters and see result
    func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {

        guard let labelText = self.text else { return }

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = lineSpacing
        paragraphStyle.lineHeightMultiple = lineHeightMultiple

        let attributedString:NSMutableAttributedString
        if let labelattributedText = self.attributedText {
            attributedString = NSMutableAttributedString(attributedString: labelattributedText)
        } else {
            attributedString = NSMutableAttributedString(string: labelText)
        }

        // Line spacing attribute
        attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))

        self.attributedText = attributedString
    }
}

Now call extension function

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"

// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) .  // try values 1.0 to 5.0

// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0

Or using label instance (Just copy & execute this code to see result)

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40

// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))

// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))

label.attributedText = attrString

Swift 3

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
attrString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
label.attributedText = attrString
Share:
260,717

Related videos on Youtube

Abhinav
Author by

Abhinav

Updated on February 12, 2021

Comments

  • Abhinav
    Abhinav about 3 years

    Is it possible to reduce the gap between text, when put in multiple lines in a UILabel? We can set the frame, font size and number of lines. I want to reduce the gap between the two lines in that label.

  • ıɾuǝʞ
    ıɾuǝʞ over 11 years
    Since iOS 6.0, you can control it via NSAttributedString (also available in properties of UILable in Xcode's interface builder).
  • Denis Kutlubaev
    Denis Kutlubaev over 11 years
    This worked for me, thanks. I also tried to use MTLabel, but this one was better.
  • esreli
    esreli almost 11 years
    Does anyone know if MSLabel supports the '\n' character?
  • lothorp
    lothorp over 10 years
    Interestingly, as near as I can tell, you can add extra spacing between the lines, but not reduce it via the NSParagraphStyle when using an NSAttributedString. (I may need to do more testing of the other modifyable properties, but the lineSpacing property only allows you to increase it.)
  • d.ennis
    d.ennis over 10 years
    see my answer to see a way using NSAttributedString
  • infinity26
    infinity26 over 10 years
    Line height is font size dependent. Line spacing is just that, line spacing. You may get things to work out by just setting min/max line height, but that's only because the current font sizes you're using aren't greater than the line height boundaries. Per the documentation: "... glyphs and graphics exceeding this height will overlap neighboring lines ... Although this limit applies to the line itself, line spacing adds extra space between adjacent lines."
  • Mike S
    Mike S over 9 years
    The attributedString must be an NSMutableAttributedString (NOT NSAttributedString)
  • Dom Vinyard
    Dom Vinyard over 9 years
    @livingtech That is infuriating, and I believe you are correct. Have you found any workarounds?
  • CodyMace
    CodyMace over 9 years
    Here's what I did and it works great. This is using TTTAttributedLabel, but it should work for and AttributedString: NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineSpacing = 1; [mutableAttributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:whole];
  • Allen
    Allen over 9 years
    Take more advantages of storyboard!
  • Allen
    Allen over 9 years
    The first line code should be NSMutableAttributedString *attributedString = [NSMutableAttributedString alloc]initWithString:@"sample text"];
  • Zoyt
    Zoyt over 9 years
    This is exactly what I needed (I needed to compress the lines). Thanks a lot!
  • PaperThick
    PaperThick over 9 years
    Using this option seems to break my ib every time, does anyone know what the issue could be there?
  • Anton Gaenko
    Anton Gaenko over 9 years
    @PaperThick have the same issue in 6.1.1. It "harlem shake" for few minutes. Doesn't know how to fix it :) Xcode Shaking
  • Marcos Curvello
    Marcos Curvello about 9 years
    Is there a way to set custom fonts this way ? I can't seem to change that helvetica neue to any other font.
  • lawicko
    lawicko about 9 years
    +1, If you want to reduce the spacing between lines, this is what you want to do. The real line spacing is most likely 0 by default, this is why people report you can only increase it. The problem with spacing being too big comes from the line height being too big, this is why this will get the job done 99% of the time.
  • Fabien Warniez
    Fabien Warniez about 9 years
    Using iOS 8.2 I was able to to reduce it. You can't set it to 0, however.
  • Theo
    Theo almost 9 years
    The lineSpacing property of the NSMutableParagraphStyle is never negative, so the line height cannot be reduced with this approach. To answer the question, you have to use another property, see @d.ennis answer.
  • Anconia
    Anconia almost 9 years
    This is a great solution. Unfortunately Xcode continues to disappoint . . . freezes every time I open this box
  • andrew k
    andrew k almost 9 years
    @Anconia Indeed, an unworkable solution. I've found that switching back to a plain text label will crash Xcode 6.3.2. I had to delete the label and start again.
  • ED-209
    ED-209 almost 9 years
    Xcode 6.3.1 when it Harlem Shakes it looks like its broken, but if you click elsewhere eventually it'll go away and all seems ok.
  • ED-209
    ED-209 almost 9 years
    If you enable 'Attributed', and then open the file as source code you can edit the 'lineHeightMultiple' manually, and therefore bypass the Harlem Shake bug
  • Pichirichi
    Pichirichi over 8 years
    @Marcos it is only working in system font, there is a radar about it for several versions, at this stage customer fonts only work via the CODe and not from the interface builder.
  • dvs
    dvs over 8 years
    The shake bug is still there in Xcode 7.1.1. Careful what you do while it's shaking, Xcode will queue your clicks and keypresses and fire them all at once after it stops. I ended up having multiple source files modified and moved around. Edit the value directly in the storyboard XML to be safe until this absurd bug is fixed.
  • BigRon
    BigRon over 8 years
    Storyboard and I don't get along, but this is great. +1000
  • LulzCow
    LulzCow about 8 years
    @azdev for anyone still looking at this, I'm on longer getting the shakes in Xcode 7.3, but I think this is the first version where it hasn't been a problem
  • virsunen
    virsunen almost 8 years
    Just to clarify something in this thread. If you want to shrink the line spacing set the line height to 1.0, and then setLineHeightMultiple to a lower value < 1.0, like: [paragraphStyle setLineHeightMultiple:0.8] or paragraphStyle.lineHeightMultiple = 0.8
  • mfaani
    mfaani over 7 years
    @MarcosCurvello My solution here is a workaround that may be useful.
  • mfaani
    mfaani over 7 years
    remember if you doing this while you are also using Storyboard for this label, then be sure to set your label's lines to 0
  • mfaani
    mfaani over 7 years
    Why don't you just directly set the lineSpacing and forget about setting lineHeightMultiple?
  • Agustin Meriles
    Agustin Meriles over 7 years
    Because the key to reduce the line height is 'lineHeightMultiple', no lineSpacing
  • mfaani
    mfaani over 7 years
    say you want your line height to be 1.4, why can't you just write .lineSpacing = 1.4 and forget all about .lineHeightMultiple...
  • mfaani
    mfaani over 7 years
    Hah! I tried, and I didn't work, but I wonder why I don't see other answers here not using your mechanism, I mean they just directly set the lineSpacing. See the accepted answer...
  • mfaani
    mfaani over 7 years
    1) why are mentioning tableViewCell is there any discussion about a tableView or a cell? 2) when we are changing the layout, why don't we need to call 'setNeedsDisplay' again?
  • Mazyod
    Mazyod over 7 years
    @Honey A UI element is required to see the feature in action. Any will do. Other answers use UILabel, I used NSTextField within a NSTableCellView. Layout and drawing are separate things. setNeedsDisplay is for drawing and rendering updates.
  • Albert Bori
    Albert Bori over 7 years
    This is the only answer I could find that uses the actual line height value (instead of a ratio) common to design applications such as Photoshop, Sketch, CSS, etc.
  • UKDataGeek
    UKDataGeek almost 7 years
    This seems to push my uilabel downwards when i put it in a stackview- anyone have a working project?
  • Russell Warwick
    Russell Warwick over 6 years
    This should help with it. You can then assign your label to this custom class within the storyboard and use it's parameters directly within the properties.
  • Neuron
    Neuron over 6 years
    please don't put content related to your answer in the comments. your answer should be helpful without having to read through the comments
  • mfaani
    mfaani over 5 years
    FWIW this is a terrible yet workable solution. Hence I'm keeping it.
  • Nithin Michael
    Nithin Michael almost 5 years
    Add the line " paragraphStyle.alignment = self.textAlignment" to keep the original alignment . Otherwise, the text will be left aligned.
  • iDeveloper
    iDeveloper over 4 years
    You saved me friend :)
  • cabyambo
    cabyambo over 4 years
    It works, but you have to make sure you've already assigned text to the label. Otherwise it will crash when your code tries to unwrap the text attribute
  • christostsang
    christostsang about 4 years
    For anyone loosing ellipsis on large texts, then use: paragraphStyle.lineBreakMode = .byTruncatingTail
  • Pavel Alexeev
    Pavel Alexeev almost 4 years
    extra padding must be (lineHeightMultiple - 1.0) * font.pointSize, right?
  • phatmann
    phatmann almost 4 years
    The code above as-is seemed to work for me. But maybe you are right. Did you try your change? @PavelAlexeev
  • Pavel Alexeev
    Pavel Alexeev almost 4 years
    No, I stick with lineSpacing instead of lineHeightMultiple :)
  • Shrikant Phadke
    Shrikant Phadke almost 3 years
    what worked for me is this. extension UILabel { func setLineHeight(lineHeight: CGFloat) { let text = self.text if let text = text { let attributedString = NSMutableAttributedString(string: text) let style = NSMutableParagraphStyle() style.lineHeightMultiple = lineHeight attributedString.addAttribute(.paragraphStyle, value: style, range: NSRange(location: 0, length: text.count)) self.attributedText = attributedString } } }
  • Wahab Khan Jadon
    Wahab Khan Jadon almost 2 years
    This solution works for me i just change paragraphStyle.alignment = .center to paragraphStyle.lineBreakMode = .byTruncatingTail paragraphStyle.baseWritingDirection = NSParagraphStyle.defaultWritingDirection(forLanguage: GeneralMethods.getSelectedLanguage().stringValue) and its automatically adopt direction according to selected language.