Set UILabel line spacing
Asked Answered
E

10

103

How can I modify the gap between lines (line spacing) in a multiline UILabel?

Endor answered 7/10, 2010 at 9:58 Comment(0)
M
126

Edit: Evidently NSAttributedString will do it, on iOS 6 and later. Instead of using an NSString to set the label's text, create an NSAttributedString, set attributes on it, then set it as the .attributedText on the label. The code you want will be something like this:

NSMutableAttributedString* attrString = [[NSMutableAttributedString  alloc] initWithString:@"Sample text"];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:24];
[attrString addAttribute:NSParagraphStyleAttributeName
    value:style
    range:NSMakeRange(0, strLength)];
uiLabel.attributedText = attrString;

NSAttributedString's old attributedStringWithString did the same thing, but now that is being deprecated.

For historical reasons, here's my original answer:

Short answer: you can't. To change the spacing between lines of text, you will have to subclass UILabel and roll your own drawTextInRect, create multiple labels, or use a different font (perhaps one edited for a specific line height, see Phillipe's answer).

Long answer: In the print and online world, the space between lines of text is known as "leading" (rhymes with 'heading', and comes from the lead metal used decades ago). Leading is a read-only property of UIFont, which was deprecated in 4.0 and replaced by lineHeight. As far as I know, there's no way to create a font with a specific set of parameters such as lineHeight; you get the system fonts and any custom font you add, but can't tweak them once installed.

There is no spacing parameter in UILabel, either.

I'm not particularly happy with UILabel's behavior as is, so I suggest writing your own subclass or using a 3rd-party library. That will make the behavior independent of your font choice and be the most reusable solution.

I wish there was more flexibility in UILabel, and I'd be happy to be proven wrong!

Manutius answered 11/10, 2010 at 18:38 Comment(5)
I have done it with sub-classing UILabel, basically idea is to divide label text into tokens, and then identity length of each token, create a separate label for each token and append one after another. Thats it.Endor
Lies! ;) You can patch a font file to change the line height - see my answer on this page.Lambkin
I'm led to believe there's a way to do this with NSAttributedString. If you need labels with attributed strings in pre iOS 6, check out OHAttributedLabel.Ruddie
Do it with NSAttributesString if you use iOS >= 6. ExampleGethsemane
This is Simple and Working Fine.Tambourin
A
75

Starting in ios 6 you can set an attributed string in the UILabel:

NSString *labelText = @"some text"; 
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:40];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
cell.label.attributedText = attributedString ;
Aracelyaraceous answered 17/4, 2013 at 9:54 Comment(1)
thanks! i'd add that using AttributedString disables for example label's text alignment, so you have to add it to the paragraph style.Traction
W
56

You can control line spacing in the storyboard:

duplicate question

Walloper answered 20/12, 2014 at 23:59 Comment(4)
However in Xcode 6.1.1 selecting the label and changing the line value in the attributed panel will cause the panel to flicker and lock the application. I have only been able to exit the panel by force-quitting Xcode.Roommate
Thumbs up for the animationLecialecithin
In version 7.1 the panel flicks and it doesn't have any effect on run time. Had to do it in code.Beatrice
440 watt electricity ran through my panel just now ;)Maurilia
M
24

From Interface Builder:

enter image description here

Programmatically:

SWift 4

Using label extension

extension UILabel {

    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 = "Set\nUILabel\nline\nspacing"
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 = "Set\nUILabel\nline\nspacing"
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
Methanol answered 4/3, 2017 at 5:38 Comment(1)
Need to pass only one arguement lineSpacing or multipleLineheight , can t pass both arguenemt other wise no result will come, i thinkMaas
L
16

My solution was to patch the font file itself and fix its line height definitely. http://mbauman.net/geek/2009/03/15/minor-truetype-font-editing-on-a-mac/

I had to modify 'lineGap', 'ascender', 'descender' in the 'hhea' block (as in the blog example).

Lambkin answered 22/5, 2012 at 13:23 Comment(5)
Super cool! Those OS X font tools also worked for my OTF font (although it only specifies TTF...). My font had line-height 1000 (!), I changed it to 0 and voila. I had miles and miles of empty space below the text on each line.Lyall
I can't believe this is the best solution (no offense!), but it is by far the simplest. I used the free (Windows) software Type Light (and under Font | Metrics | Advanced you can modify lineGap) to edit my fonts. It also allows you to "rename" the fonts, which I couldn't figure out how to do using the tool Philippe mentioned.Outwash
Also see my answer to a similar question for more specifics: https://mcmap.net/q/23546/-custom-installed-font-not-displayed-correctly-in-uilabelSquirrel
@iamjustaprogrammer It's online again.Leucine
The link is dead, again.Alverta
A
8

This guy created a class to get line-height (without using CoreText, as MTLabel library) : https://github.com/LemonCake/MSLabel

Airhead answered 16/5, 2012 at 12:4 Comment(0)
S
7

Best thing I found is: https://github.com/mattt/TTTAttributedLabel

It's a UILabel subclass so you can just drop it in, and then to change the line height:

myLabel.lineHeightMultiple = 0.85;
myLabel.leading = 2;
Stenopetalous answered 26/6, 2013 at 13:45 Comment(0)
L
4

I've found 3rd Party Libraries Like this one:

https://github.com/Tuszy/MTLabel

To be the easiest solution.

Lockman answered 15/9, 2011 at 8:48 Comment(0)
F
2

Here's some swift-code for you to set the line spacing programmatically

let label = UILabel()

let attributedText = NSMutableAttributedString(string: "Your string")
let paragraphStyle = NSMutableParagraphStyle()

//SET THIS:
paragraphStyle.lineSpacing = 4
//OR SET THIS:
paragraphStyle.lineHeightMultiple = 4

//Or set both :)

let range = NSMakeRange(0, attributedText.length)
attributedText.addAttributes([NSParagraphStyleAttributeName : paragraphStyle], range: range)
label.attributedText = attributedText
Father answered 14/2, 2017 at 13:44 Comment(0)
D
0

Of course, Mike's answer doesn't work if you pass the string programmatically. In this case you need to pass a attributed string and change it's style.

NSMutableAttributedString * attrString = [[NSMutableAttributedString alloc] initWithString:@"Your \nregular \nstring"];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:4];
[attrString addAttribute:NSParagraphStyleAttributeName
                   value:style
                   range:NSMakeRange(0, attrString.length)];
_label.attributedText = attrString;
Demoss answered 24/1, 2017 at 21:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.