89

I'm trying to make a UIButton that has two lines of text in its titleLabel. This is the code I'm using:

UIButton *titleButton = [[UIButton alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
titleButton.titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
[titleButton setTitle:@"This text is very long and should get truncated at the end of the second line" forState:UIControlStateNormal];
titleButton.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
titleButton.titleLabel.numberOfLines = 2;
[self addSubview:titleButton];

When I try this, the text only appears on one line. It seems the only way to achieve more than one line of text in UIButton.titleLabel is to set numberOfLines=0 and use UILineBreakModeWordWrap. But this doesn't guarantee the text to be exactly two lines.

Using a plain UILabel, however, does work:

UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
titleLabel.text = @"This text is very long and should get truncated at the end of the second line";
titleLabel.numberOfLines = 2;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
[self addSubview:titleLabel];

    

Does anyone know how to make the UIButton work with two lines? Is the only solution to create a separate UILabel to hold the text, and add it as a subview of the button?

pkamb
  • 33,281
  • 23
  • 160
  • 191
marketer
  • 41,507
  • 11
  • 37
  • 40
  • 1
    Have you seen this ? - http://stackoverflow.com/questions/604632/how-do-you-add-multi-line-text-to-a-uibutton – Viraj Oct 20 '11 at 06:33
  • Viraj, yes, if you set `numberOfLines=0` and use `UILineBreakModeWordWrap`, you can get multiple lines. The problem with that is it could give more than two lines if the text is too long. I want _exactly_ two lones with an elipses at the end of the second line (if the text is too long). – marketer Oct 20 '11 at 07:01
  • Oh, then I guess adding subview may be the only way to go. – Viraj Oct 20 '11 at 07:14

6 Answers6

146

You don't need to add a UILabel to the UIButton. That's just extra objects and work.

Set these properties on the titleLabel of your button.

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2;//if you want unlimited number of lines put 0

Swift:

button.titleLabel!.lineBreakMode = NSLineBreakMode.ByWordWrapping
button.titleLabel!.numberOfLines = 2//if you want unlimited number of lines put 0
fede1608
  • 2,808
  • 1
  • 16
  • 17
Sean
  • 2,106
  • 2
  • 16
  • 24
  • 6
    This is the 2013 and as of today this is the state of the art solution. – Klaas May 28 '13 at 19:04
  • @Blip you can't unfortunately and need to do it in code. Might be worth filing a bug report with Apple requesting this functionality. – bpapa Dec 08 '15 at 15:38
  • @bpapa Yep I agree, storyboards should be more flexible. – Blip Dec 08 '15 at 23:28
  • 8
    This works for me, however it breaks the default behaviour of the button's `intrinsicContentSize`, which still returns a height that corresponds to just one line of text. I fixed it by overriding the button's `intrinsicContentSize` where I set the height to be `[self.titleLabel sizeThatFits(CGSizeMake(self.titleLabel.frame.size.width, CGFLOAT_MAX)].height`. – Elise Feb 12 '16 at 14:08
  • @WillVonUllrich because you can only change the accepted answer when it is edited. I added these answers to the accepted one so it will help the people that do not look further then the accepted answer. – Totumus Maximus Jan 09 '17 at 13:16
89

Updated answer for more recent iOS versions

Since this is the accepted answer, added @Sean's answer here:

Set these properties on the titleLabel of your button.

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2; // if you want unlimited number of lines put 0

Swift 3 and 4:

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.numberOfLines = 2 // if you want unlimited number of lines put 0

Original answer for an older version of iOS

If you want 2 lines of text on top of your UIButton you should add a UIlabel on top of it that does precisely that.

UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
titleLabel.text = @"This text is very long and should get truncated at the end of the second line";
titleLabel.numberOfLines = 2;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
[myButton addSubview:titleLabel]; //add label to button instead.

Updated for interface builder solution

Added @Borut Tomazin's answer for a more complete answer. Updated this part again since the answer of @Borut Tomazin was improved.

You can do this much easier, with no code required. In Interface Builder set Line Break on UIButton to Word Wrap. Than you can insert multiple lines of title. Just hit Option + Return keys to make new line. You will also need to add this to the User Defined Runtime Attribute in Interface Builder:

titleLabel.textAlignment Number [1]
Joseph Francis
  • 1,111
  • 1
  • 15
  • 26
Totumus Maximus
  • 7,543
  • 6
  • 45
  • 69
88

You can do this much easier, with no code required. In Interface Builder set Line Break on UIButton to Word Wrap. Than you can insert multiple lines of title. Just hit Option + Return keys to make new line. You will also need to add this to the User Defined Runtime Attribute in Interface Builder:

titleLabel.textAlignment Number [1]

It's that simple. Hope it helps...

BlackTigerX
  • 6,006
  • 7
  • 38
  • 48
Borut Tomazin
  • 8,041
  • 11
  • 78
  • 91
  • 1
    This solution is better (less objects, code) than the currently accepted one, for simple cases. – Jonathan Zhan Nov 15 '12 at 07:37
  • 1
    You set the exact same properties as you would programmatically so your argument "less objects" is invalid. Code is maybe less. But it is more readable. Take your pick ;) – Totumus Maximus Nov 15 '12 at 09:22
  • Oh, I was unclear I think. Thanks for trying to clarify. Was not so much concerned with the fact that it is done in IB vs Code. More to do with the fact that you don't need to add an additional label with Borut's solution, and that it also accomplishes the same thing. But yes, both work great. :) – Jonathan Zhan Nov 19 '12 at 10:26
  • it's really overwhelming to need to go to code behind for such a basic task. – Can Poyrazoğlu Aug 21 '13 at 08:37
  • 3
    You can achieve the same goal 100% codeless by adding the `titleLabel.textAlignment` *User Defined Runtime Attribute* in Interface Builder and set it to *Number* = 1 (NSTextAlignmentCenter's value). – 0xced Nov 11 '14 at 22:36
  • `UITextAlignmentCenter` is deprecated, use `NSTextAlignmentCenter` instead. – Dylan Vander Berg May 28 '15 at 16:25
  • @BlackTigerX I will add it to mine since the OP is not anywhere to be seen. – Totumus Maximus Jul 07 '17 at 14:29
21
 button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;

button.titleLabel.textAlignment = NSTextAlignmentCenter;

[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];
Suraj K Thomas
  • 5,773
  • 4
  • 52
  • 64
9

To avoid completely the need to edit code, and thus the need to subclass your view, in Xcode5 and greater you can follow Borut Tomazin suggestion:

In Interface Builder (or storyboard) set Line Break to Word Wrap. Than you can insert multiple lines of title. Just hit Option + Return keys to make new line.

and then, in the User Defined Runtime Attributes you can add

Key path: titleLabel.textAlignment
Type: Number
Value: 1

Note: this may be not completely "future proof" since we are translating the UITextAlignmentCenter constant into its numerical value (and that constant may change as new iOS versions are released), but it seems safe in the near future.

furins
  • 4,979
  • 1
  • 39
  • 57
1

You can modify the needed value directly from Storyboard. Select the button, go to the identity inspector and add the following key-value pair in the "User defined runtime attributes" section:

enter image description here

Arik Segal
  • 2,963
  • 2
  • 17
  • 29