2 line text UIButton - ios

I have a UIButton and the text of the button is filled by a randomiser.
However my problem is that sometimes the number of characters in a text is too many, leading to the button now showing the whole text.
Would it be possible to check if the characters are too many and then have it drop the rest of the text to another text line? So basically having to text lines instead of one for the UIButton?

Objectivc-C
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2;
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if u need
else use this
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
[button setTitle: #"Line1\nLine2" forState: UIControlStateNormal];
Swift
button.titleLabel!.lineBreakMode = .ByWordWrapping
button.titleLabel!.numberOfLines = 2
button.titleLabel!.textAlignment = .Center
else use this
button.titleLabel!.lineBreakMode = .ByWordWrapping
button.titleLabel!.textAlignment = .Center
button.setTitle("Line1\nLine2", forState: .Normal)
Swift3
buttonName.titleLabel!.lineBreakMode = .byWordWrapping
buttonName.titleLabel!.textAlignment = .center
buttonName.setTitle("Line1\nLine2", for: .normal)

In the Interface Builder, change the Line Break mode to Word Wrap for the UIButton control:
And to center the text, make the title Attributed instead of Plain.

Assuming you are using a storyboard or .xib file, click on your button and open the Attributes inspector on the right, then in the Button section, look for the 'Line Break' field. Drop this down and you will see 2 options (among others) - 'Character wrap' and 'Word wrap', these provide the functionality you are after.
alternatively In code you can use one of the following
[BUTTON setLineBreakMode:NSLineBreakByWordWrapping]
[BUTTON setLineBreakMode:NSLineBreakByCharWrapping]

I had a problem with UILabels growing when auto layout was used rather than word wrapping. The solution was to set the preferredMaxLayoutWidth to force it to wrap the text.
For a button you can do the same thing using:
button.titleLabel.preferredMaxLayoutWidth = <max width required>.

Related

iOS multiline label in Interface builder

How can I make a multiline UILabel in interface builder for iOS? I tried the UITextView but it didn't quite suit my needs.
How can I add multiline (text) in label?
You can use numberOfLines property which defines maximum number of lines a label can have. By default, it's 1. Setting it to 0 means the label will have unlimited lines.
You can do it in code:
textLabel.numberOfLines = 5 // for example
Or in Interface Builder:
Hit Control+Enter to add a line in UILabel in Interface Builder/Storyboard.
Thanks AppleVijay!
Also to call sizeToFit, like this:
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;
[label sizeToFit];
The height will be automatically computed.
set width of label as u needed small then use IB to set line breaks to word wrap
or use with code like this
I found a solution.
One just has to add the following code:
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;
Set number of lines zero for dynamic text information, it will be useful when your text are varying.
Programatically (Swift 3)
var label = UILabel()
let stringValue = "iOS\nmultiline\nlabel\nin\nInterface\nbuilder"
label.text = stringValue
label.numberOfLines = 0 // Set 0, if number of lines not specified.
label.lineBreakMode = .byTruncatingTail // or .byWrappingWord
label.minimumScaleFactor = 0.8 . // It is not required but nice to have a minimum scale factor to fit text into label frame
Using Inetrface Builder
Note: It is not required to set Minimum Font Scale, but nice to have a minimum scale factor to fit text into label frame.
Number of lines is visible in IB with Plain UILabels
set lines field as 0 . It will create multiple lines as per the provided space to the label.
In iOS7 (Xcode5) you shold set the lines of UILabel to 0 for unlimited multiple input in storyboard.
The most important is to set the height of the UILabel can hold the lines of input you are going to set.
textLabel.lineBreakMode = UILineBreakModeWordWrap;
textLabel.numberOfLines = 0;
CGSize size = [[[arrNewsFeed objectAtIndex:row] objectForKey:#"c"] sizeWithFont:[UIFont systemFontOfSize:14.0] constrainedToSize:CGSizeMake(188, CGFLOAT_MAX)
lineBreakMode:NSLineBreakByTruncatingTail];
textLabel.frame = (CGRect){.origin = cell.lblNewsDescription.frame.origin, .size = size};
If you set the numberOfLines property equal to 0, the label will automatically adjust to the required number of lines of the given text.
I had been struggling with this for a long time.
I just wanted my label text to appear on the second line. But whatever I do, it would just overflow the UILabel box. For me, changing the autoresizing in size inspector worked. Simple fix.
May be someone might find it helpful who is looking for something similar.
For X-Code 7.2
-- Select UILabel
-- Attributes inspector
-- Text - Select Attributed
After this you can see some more attribute you can add into you label, in which you can also find number of Lines. Which make your label multiline.

How can I set the title of a UIButton as left-aligned?

I need to display an email address on the left side of a UIButton, but it is being positioned to the centre.
Is there any way to set the alignment to the left side of a UIButton?
This is my current code:
UIButton* emailBtn = [[UIButton alloc] initWithFrame:CGRectMake(5,30,250,height+15)];
emailBtn.backgroundColor = [UIColor clearColor];
[emailBtn setTitle:obj2.customerEmail forState:UIControlStateNormal];
emailBtn.titleLabel.font = [UIFont systemFontOfSize:12.5];
[emailBtn setTitleColor:[[[UIColor alloc]initWithRed:0.121 green:0.472 blue:0.823 alpha:1]autorelease] forState:UIControlStateNormal];
[emailBtn addTarget:self action:#selector(emailAction:) forControlEvents:UIControlEventTouchUpInside];
[elementView addSubview:emailBtn];
[emailBtn release];
Set the contentHorizontalAlignment:
// Swift
emailBtn.contentHorizontalAlignment = .left;
// Objective-C
emailBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
You might also want to adjust the content left inset otherwise the text will touch the left border:
// Swift 3 and up:
emailBtn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0);
// Objective-C
emailBtn.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
You can also use interface builder if you don't want to make the adjustments in code.
Here I left align the text and also indent it some:
Don't forget you can also align an image in the button too.:
In Swift 3+:
button.contentHorizontalAlignment = .left
Swift 4+
button.contentHorizontalAlignment = .left
button.contentVerticalAlignment = .top
button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
UIButton *btn;
btn.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
Using emailBtn.titleEdgeInsets is better than contentEdgeInsets, in case you don't want to change the whole content position inside the button.
Here is explained how to do it and why it works so:
http://cocoathings.blogspot.com/2013/03/how-to-make-uibutton-text-left-or-right.html
in xcode 8.2.1 in the interface builder it moves to:
There is a small error in the code of #DyingCactus.
Here is the correct solution to add an UILabel to an UIButton to align the button text to better control the button 'title':
NSString *myLabelText = #"Hello World";
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
// position in the parent view and set the size of the button
myButton.frame = CGRectMake(myX, myY, myWidth, myHeight);
CGRect myButtonRect = myButton.bounds;
UILabel *myLabel = [[UILabel alloc] initWithFrame: myButtonRect];
myLabel.text = myLabelText;
myLabel.backgroundColor = [UIColor clearColor];
myLabel.textColor = [UIColor redColor];
myLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:14.0];
myLabel.textAlignment = UITextAlignmentLeft;
[myButton addSubview:myLabel];
[myLabel release];
Hope this helps....
Al
For Swift 2.0:
emailBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
This can help if any one needed.
In Swift 5.0 and Xcode 10.2
You have two ways to approaches
1) Direct approach
btn.contentHorizontalAlignment = .left
2) SharedClass example (write once and use every ware)
This is your shared class(like this you access all components properties)
import UIKit
class SharedClass: NSObject {
static let sharedInstance = SharedClass()
private override init() {
}
}
//UIButton extension
extension UIButton {
func btnProperties() {
contentHorizontalAlignment = .left
}
}
In your ViewController call like this
button.btnProperties()//This is your button
Try
button.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
tl;dr: Using UIButton.Configuration - do titleAlignment = .center but also add a subtitle and make its font microscopic.
So, we're on iOS 15+, we're using the new UIButton.Configuration APIs, buttons now go multi-line by default and you're trying to figure out - how do I make the button's title be centered or trailing aligned, as opposed to the default (leading). For example you have an image and a button title underneath and and you want it centered.
Seems reasonable to try this:
configuration.titleAlignment = .center
But it doesn't change anything.
By trying thing out in Interface Builder, I noticed the following: titleAlignment only has an effect if there is a subtitle along with the title.
I am not sure if this is an omission on Apple's side (which might be fixed later) or if there is a good reason for it. In any case, we need a way to make it work without a subtitle. Perhaps some clever contentInset or UIControl.contentHorizontalAlignment can do the trick, but I'd be worried to use these in cases where we have to think about other languages, dynamic type etc.
Here's a solution which is still hacky, but would do the job:
Add a subtitle which contains just a space, then make the font microscopic, e.g. 0.01.
This is how to do it in code, assuming you are already working with a UIButton.Configuration:
configuration.titleAlignment = .center
configuration.title = "Hello hi"
configuration.subtitle = " "
configuration.subtitleTextAttributesTransformer = UIConfigurationTextAttributesTransformer({ input in
var output = input
output.font = .systemFont(ofSize: 0.01)
return output
})
Not an ideal solution and it might break in the future, but for some use cases the best available solution at the moment.
if you use button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10), you will get an warning that states 'contentEdgeInsets' was deprecated in iOS 15.0: This property is ignored when using UIButtonConfiguration. An alternative solution is:
iOS 15.0+
var button: UIButton = {
let button = UIButton(configuration: .filled())
button.configuration?.contentInsets = NSDirectionalEdgeInsets(top: 16, leading: 20, bottom: 16, trailing: 20)
button.contentHorizontalAlignment = .leading
return button
}()
SwiftUI
You should change the alignment property of the .frame modifier applied to the Text. Additionally, set the multiline text alignment to .leading.
Button {
// handler for tapping on the button
} label: {
Text("Label")
.frame(width: 200, alignment: .leading)
.multilineTextAlignment(.leading)
}

How to add line break for UILabel?

Let see that I have a string look like this:
NSString *longStr = #"AAAAA\nBBBBB\nCCCCC";
How do I make it so that the UILabel display the message like this
AAAAA
BBBBB
CCCCC
I don't think \n is recognized by UILabel, so is there anything that I can put inside NSString so that UILabel knows that it has to create a line break there?
Use \n as you are using in your string.
Set numberOfLines to 0 to allow for any number of lines.
label.numberOfLines = 0;
Update the label frame to match the size of the text using sizeWithFont:. If you don't do this your text will be vertically centered or cut off.
UILabel *label; // set frame to largest size you want
...
CGSize labelSize = [label.text sizeWithFont:label.font
constrainedToSize:label.frame.size
lineBreakMode:label.lineBreakMode];
label.frame = CGRectMake(
label.frame.origin.x, label.frame.origin.y,
label.frame.size.width, labelSize.height);
Update : Replacement for deprecatedsizeWithFont:constrainedToSize:lineBreakMode:
Reference, Replacement for deprecated sizeWithFont: in iOS 7?
CGSize labelSize = [label.text sizeWithAttributes:#{NSFontAttributeName:label.font}];
label.frame = CGRectMake(
label.frame.origin.x, label.frame.origin.y,
label.frame.size.width, labelSize.height);
Use option-return when typing in the little box in Interface Builder to insert a line feed (\n). In Interface Builder's Label attributes, set # Lines = 0.
Select the label and then change Lines property to 0 like in the above image, and then use \n in your string for line break.
In the interface builder, you can use Ctrl + Enter to insert /n to the position you want.
This way could implement the following situation
aaaaaaaaaa
If you read a string from an XML file, the line break \n in this string will not work in UILabel text. The \n is not parsed to a line break.
Here is a little trick to solve this issue:
// correct next line \n in string from XML file
NSString *myNewLineStr = #"\n";
myLabelText = [myLabelText stringByReplacingOccurrencesOfString:#"\\n" withString:myNewLineStr];
myLabel.text = myLabelText;
So you have to replace the unparsed \n part in your string by a parsed \n in a hardcoded NSString.
Here are my other label settings:
myLabel.numberOfLines = 0;
myLabel.backgroundColor = [UIColor lightGrayColor];
myLabel.textColor = [UIColor redColor];
myLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:14.0];
myLabel.textAlignment = UITextAlignmentCenter;
Most important is to set numberOfLines to 0 (= unlimited number of lines in label).
No idea why Apple has chosen to not parse \n in strings read from XML?
You have to set the numberOfLines property on the UILabel. The default is 1, if you set it to 0 it will remove all limits.
Important to note it's \n (backslash) rather than /n.
For those of you who want an easy solution, do the following in the text Label input box in Interface Builder:
Make sure your number of lines is set to 0.
Alt + Enter
(Alt is your option key)
Cheers!
In Swift 2.2, > iOS 8
I've set Lines = 0 on Storyboard, under Attribute Inspector and linked a referencing outlet to the label. Then use in controller like this:
#IBOutlet weak var listLabel: UILabel!
override func viewDidLoad() {
...
listLabel.text = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8"
}
In xCode 11, Swift 5 the \n works fine, try the below code:
textlabel.numberOfLines = 0
textlabel.text = "This is line one \n This is line two \n This is line three"
Just do it like this
NSString * strCheck = #"A\nB";
strCheck = [strCheck stringByReplacingOccurrencesOfString:#"\\n" withString:#"\n"]; //This is to prevent for fetching string from plist or data structure
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.text = strCheck;
// DO not forget to set numberOfLines to zero
UILabel* locationTitle = [[UILabel alloc] initWithFrame:CGRectMake(5, 30, 230, 40)];
locationTitle.font = [UIFont systemFontOfSize:13.0];
locationTitle.numberOfLines = 0;
locationTitle.text = [NSString stringWithFormat:#"Eaton industries pvt. Ltd \nUK Apr 12"];
[cell addSubview:locationTitle];
If your using a UILabel you have to remember that the default setting is 1 line, so it does not matter how many breaks you add (\n or \r), you need to make sure it is set to more than one line so it could be allowed to append more lines.
One alternative is to use UITextView which is really meant for multilines.
You can easily achieve this in XCode attribute section of the UILabel, see screenshot:
On Xcode 6, you can just use \n even inside a string when using word wrap. It will work. So for example:
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, screenRect.size.width, 50)];
label.textAlignment = NSTextAlignmentCenter;
label.text = #"This will be on the first line\nfollowed by a line under it.";
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;
In my case also \n was not working, I fixed issue by keeping number of lines to 0 and copied and pasted the text with new line itself for example instead of Hello \n World i pasted
Hello
World
in the interface builder.
Just using label.numberOfLines = 0;
textLabel.text = #"\nAAAAA\nBBBBB\nCCCCC";
textLabel.numberOfLines = 3; \\As you want - AAAAA\nBBBBB\nCCCCC
textLabel.lineBreakMode = UILineBreakModeWordWrap;
NSLog(#"The textLabel text is - %#",textLabel.text);
For anyone else that might have trouble with sizeWithFont:constrainedToSize:lineBreakMode: or anyone switching to ios8 (the method is deprecated as of ios7), I adjusted my height by using sizeToFit instead.
UILabel *label;
label.numberOfLines = 0;
// Setup label with desired settings
...
[label sizeToFit];
label.frame = CGRectMake(label.frame.origin.x, // Or use any desired origin
label.frame.origin.y,
label.frame.size.width, // Or use any desired width
label.frame.size.height);
NSCharacterSet *charSet = NSCharacterSet.newlineCharacterSet;
NSString *formatted = [[unformatted componentsSeparatedByCharactersInSet:charSet] componentsJoinedByString:#"\n"];
It seems wrong to me to change the label frame sizes especially when using autolayout. Using the appendFormat method seems more appropriate. Here is my example:
NSMutableString *list = [[NSMutableString alloc] init];
NSArray *textArray = #[#"AAAA", #"BBBB"];
for (NSString *string in textArray) {
[list appendFormat:#"%#\n", string.mutableCopy];
}
self.label.text = list;
self.label.numberOfLines = 0;
If you set your UILable properties from Plain to Attributed...the UILabel will hold multiline text no matter how many paragraphs for along as your UILabel height and width are set to fit the screen area you want to display the text in.
I have faced same problem, and here is, how i solved the problem. Hope this will be helpful for someone.
// Swift 2
lblMultiline.lineBreakMode = .ByWordWrapping // or use NSLineBreakMode.ByWordWrapping
lblMultiline.numberOfLines = 0
// Objective-C
lblMultiline.lineBreakMode = NSLineBreakByWordWrapping;
lblMultiline.numberOfLines = 0;
// C# (Xamarin.iOS)
lblMultiline.LineBreakMode = UILineBreakMode.WordWrap;
lblMultiline.Lines = 0;
on Xcode 6, I can use \n without problem on swift programmatically

How do you add multi-line text to a UIButton?

I have the following code...
UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = #"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];
...the idea being that I can have multi-line text for the button, but the text is always obscured by the backgroundImage of the UIButton. A logging call to show the subviews of the button shows that the UILabel has been added, but the text itself cannot be seen. Is this a bug in UIButton or am I doing something wrong?
For iOS 6 and above, use the following to allow multiple lines:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
// you probably want to center it
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if you want to
[button setTitle: #"Line1\nLine2" forState: UIControlStateNormal];
For iOS 5 and below use the following to allow multiple lines:
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
// you probably want to center it
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setTitle: #"Line1\nLine2" forState: UIControlStateNormal];
2017, for iOS9 forward,
generally, just do these two things:
choose "Attributed Text"
on the "Line Break" popup select "Word Wrap"
The selected answer is correct but if you prefer to do this sort of thing in Interface Builder you can do this:
If you want to add a button with the title centered with multiple lines, set your Interface Builder's settings for the button:
[]
For IOS 6 :
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
As
UILineBreakModeWordWrap and UITextAlignmentCenter
are deprecated in IOS 6 onwards..
To restate Roger Nolan's suggestion, but with explicit code, this is the general solution:
button.titleLabel?.numberOfLines = 0
SWIFT 3
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center
button.setTitle("Button\nTitle",for: .normal)
I had an issue with auto-layout, after enabling multi-line the result was like this:
so the titleLabel size doesn't affect the button size
I've added Constraints based on contentEdgeInsets (in this case contentEdgeInsets was (10, 10, 10, 10)
after calling makeMultiLineSupport():
hope it helps you (swift 5.0):
extension UIButton {
func makeMultiLineSupport() {
guard let titleLabel = titleLabel else {
return
}
titleLabel.numberOfLines = 0
titleLabel.setContentHuggingPriority(.required, for: .vertical)
titleLabel.setContentHuggingPriority(.required, for: .horizontal)
addConstraints([
.init(item: titleLabel,
attribute: .top,
relatedBy: .greaterThanOrEqual,
toItem: self,
attribute: .top,
multiplier: 1.0,
constant: contentEdgeInsets.top),
.init(item: titleLabel,
attribute: .bottom,
relatedBy: .greaterThanOrEqual,
toItem: self,
attribute: .bottom,
multiplier: 1.0,
constant: contentEdgeInsets.bottom),
.init(item: titleLabel,
attribute: .left,
relatedBy: .greaterThanOrEqual,
toItem: self,
attribute: .left,
multiplier: 1.0,
constant: contentEdgeInsets.left),
.init(item: titleLabel,
attribute: .right,
relatedBy: .greaterThanOrEqual,
toItem: self,
attribute: .right,
multiplier: 1.0,
constant: contentEdgeInsets.right)
])
}
}
In Xcode 9.3 you can do it by using storyboard like below,
You need to set button title textAlignment to center
button.titleLabel?.textAlignment = .center
You don't need to set title text with new line (\n) like below,
button.setTitle("Good\nAnswer",for: .normal)
Simply set title,
button.setTitle("Good Answer",for: .normal)
Here is the result,
There is a much easier way:
someButton.lineBreakMode = UILineBreakModeWordWrap;
(Edit for iOS 3 and later:)
someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
Left align on iOS7 with autolayout:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
First of all, you should be aware that UIButton already has a UILabel inside it. You can set it using –setTitle:forState:.
The problem with your example is that you need to set UILabel's numberOfLines property to something other than its default value of 1. You should also review the lineBreakMode property.
Swift 5 , For multi Line text in UIButton
let button = UIButton()
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center
button.titleLabel?.numberOfLines = 0 // for Multi line text
To fix title label's spacing to the button, set titleEdgeInsets and other properties before setTitle:
let button = UIButton()
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.numberOfLines = 0
button.titleEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 20, right: 20)
button.setTitle("Dummy button with long long long long long long long long title", for: .normal)
P.S. I tested setting titleLabel?.textAlignment is not necessary and the title aligns in .natural.
For those who are using Xcode 4's storyboard, you can click on the button, and on the right side Utilities pane under Attributes Inspector, you'll see an option for Line Break. Choose Word Wrap, and you should be good to go.
Answers here tell you how to achieve multiline button title programmatically.
I just wanted to add that if you are using storyboards, you can type [Ctrl+Enter] to force a newline on a button title field.
HTH
Setting lineBreakMode to NSLineBreakByWordWrapping (either in IB or code) makes button label multiline, but doesn't affect button's frame.
If button has dynamic title, there is one trick: put hidden UILabel with same font and tie it's height to button's height with layout; when set text to button and label and autolayout will make all the work.
Note
Intrinsic size height of one-line button is bigger than label's, so to prevent label's height shrink it's vertical Content Hugging Priority must be greater than button's vertical Content Compression Resistance.
You have to add this code:
buttonLabel.titleLabel.numberOfLines = 0;
These days, if you really need this sort of thing to be accessible in interface builder on a case-by-case basis, you can do it with a simple extension like this:
extension UIButton {
#IBInspectable var numberOfLines: Int {
get { return titleLabel?.numberOfLines ?? 1 }
set { titleLabel?.numberOfLines = newValue }
}
}
Then you can simply set numberOfLines as an attribute on any UIButton or UIButton subclass as if it were a label. The same goes for a whole host of other usually-inaccessible values, such as the corner radius of a view's layer, or the attributes of the shadow that it casts.
As to Brent's idea of putting the title UILabel as sibling view, it doesn't seem to me like a very good idea. I keep thinking in interaction problems with the UILabel due to its touch events not getting through the UIButton's view.
On the other hand, with a UILabel as subview of the UIButton, I'm pretty confortable knowing that the touch events will always be propagated to the UILabel's superview.
I did take this approach and didn't notice any of the problems reported with backgroundImage. I added this code in the -titleRectForContentRect: of a UIButton subclass but the code can also be placed in drawing routine of the UIButton superview, which in that case you shall replace all references to self with the UIButton's variable.
#define TITLE_LABEL_TAG 1234
- (CGRect)titleRectForContentRect:(CGRect)rect
{
// define the desired title inset margins based on the whole rect and its padding
UIEdgeInsets padding = [self titleEdgeInsets];
CGRect titleRect = CGRectMake(rect.origin.x + padding.left,
rect.origin.x + padding.top,
rect.size.width - (padding.right + padding.left),
rect.size.height - (padding.bottom + padding].top));
// save the current title view appearance
NSString *title = [self currentTitle];
UIColor *titleColor = [self currentTitleColor];
UIColor *titleShadowColor = [self currentTitleShadowColor];
// we only want to add our custom label once; only 1st pass shall return nil
UILabel *titleLabel = (UILabel*)[self viewWithTag:TITLE_LABEL_TAG];
if (!titleLabel)
{
// no custom label found (1st pass), we will be creating & adding it as subview
titleLabel = [[UILabel alloc] initWithFrame:titleRect];
[titleLabel setTag:TITLE_LABEL_TAG];
// make it multi-line
[titleLabel setNumberOfLines:0];
[titleLabel setLineBreakMode:UILineBreakModeWordWrap];
// title appearance setup; be at will to modify
[titleLabel setBackgroundColor:[UIColor clearColor]];
[titleLabel setFont:[self font]];
[titleLabel setShadowOffset:CGSizeMake(0, 1)];
[titleLabel setTextAlignment:UITextAlignmentCenter];
[self addSubview:titleLabel];
[titleLabel release];
}
// finally, put our label in original title view's state
[titleLabel setText:title];
[titleLabel setTextColor:titleColor];
[titleLabel setShadowColor:titleShadowColor];
// and return empty rect so that the original title view is hidden
return CGRectZero;
}
I did take the time and wrote a bit more about this here. There, I also point a shorter solution, though it doesn't quite fit all the scenarios and involves some private views hacking. Also there, you can download an UIButton subclass ready to be used.
If you use auto-layout on iOS 6 you might also need to set the preferredMaxLayoutWidth property:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;
In Swift 5.0 and Xcode 10.2
//UIButton extension
extension UIButton {
//UIButton properties
func btnMultipleLines() {
titleLabel?.numberOfLines = 0
titleLabel?.lineBreakMode = .byWordWrapping
titleLabel?.textAlignment = .center
}
}
In your ViewController call like this
button.btnMultipleLines()//This is your button
It works perfectly.
Add to use this with config file like Plist, you need to use CDATA to write the multilined title, like this:
<string><![CDATA[Line1
Line2]]></string>
If you use auto-layout.
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2
swift 4.0
btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)
Roll your own button class. It's by far the best solution in the long run. UIButton and other UIKit classes are very restrictive in how you can customize them.
In iOS 15 in 2021, Apple for the first time officially supports multi-line UIButtons via the UIButton.Configuration API.
UIButton.Configuration
A configuration that specifies the appearance and behavior of a button and its contents.
This new API is explored in What's new in UIKit as well as the session:
Meet the UIKit button system
Every app uses Buttons. With iOS 15, you can adopt updated styles to create gorgeous buttons that fit effortlessly into your interface. We'll explore features that make it easier to create different types of buttons, learn how to provide richer interactions, and discover how you can get great buttons when using Mac Catalyst.
https://developer.apple.com/videos/play/wwdc2021/10064/
self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
self.btnError.titleLabel?.textAlignment = .center
self.btnError.setTitle("Title", for: .normal)
I incorporated jessecurry's answer within STAButton which is part of my STAControls open source library. I currently use it within one of the apps I am developing and it works for my needs. Feel free to open issues on how to improve it or send me pull requests.
Adding Buttons constraints and subviews. This is how i do it in my projects, lets say its much easier like this. I literally 99% of my time making everything programmatically.. Since its much easier for me. Storyboard can be really buggy sometimes
[1]: https://i.stack.imgur.com/5ZSwl.png
My experience:
Go to "Attribut" tab.
Texting in title, press "alt+Enter" while you want to jump to next line.
And check "Word Wrap" under "Attribut --> Control" field.
picture

Adding the "Clear" Button to an iPhone UITextField

How do you add that little "X" button on the right side of a UITextField that clears the text? I can't find an attribute for adding this sub-control in Interface Builder in the iPhone OS 2.2 SDK.
Note: In Xcode 4.x and later (iPhone 3.0 SDK and later), you can do this in Interface Builder.
This button is a built-in overlay that is provided by the UITextField class, but as of the iOS 2.2 SDK, there isn't any way to set it via Interface Builder. You have to enable it programmatically.
Add this line of code somewhere (viewDidLoad, for example):
Objective-C
myUITextField.clearButtonMode = UITextFieldViewModeWhileEditing;
Swift 5.0
myUITextField.clearButtonMode = .whileEditing
You can also set this directly from Interface Builder under the Attributes Inspector.
Taken from XCode 5.1
Swift 4+:
textField.clearButtonMode = UITextField.ViewMode.whileEditing
or even shorter:
textField.clearButtonMode = .whileEditing
you can add custom clear button and control the size and every thing using this:
UIButton *clearButton = [UIButton buttonWithType:UIButtonTypeCustom];
[clearButton setImage:img forState:UIControlStateNormal];
[clearButton setFrame:frame];
[clearButton addTarget:self action:#selector(clearTextField:) forControlEvents:UIControlEventTouchUpInside];
textField.rightViewMode = UITextFieldViewModeAlways; //can be changed to UITextFieldViewModeNever, UITextFieldViewModeWhileEditing, UITextFieldViewModeUnlessEditing
[textField setRightView:clearButton];
Swift 4 (adapted from Kristopher Johnson's answer)
textfield.clearButtonMode = .always
textfield.clearButtonMode = .whileEditing
textfield.clearButtonMode = .unlessEditing
textfield.clearButtonMode = .never
Objective C :
self.txtUserNameTextfield.myUITextField.clearButtonMode = UITextFieldViewModeWhileEditing;
Swift :
txtUserNameTextfield.clearButtonMode = UITextField.ViewMode.WhileEditing;
this don't work, do like me:
swift:
customTextField.clearButtonMode = UITextField.ViewMode.Always
customTextField.clearsOnBeginEditing = true;
func textFieldShouldClear(textField: UITextField) -> Bool {
return true
}
On Xcode 8 (8A218a):
Swift:
textField.clearButtonMode = UITextField.ViewMode.whileEditing;
The "W" went from capital to non-cap "w".
func clear_btn(box_is : UITextField){
box_is.clearButtonMode = .always
if let clearButton = box_is.value(forKey: "_clearButton") as? UIButton {
let templateImage = clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate)
clearButton.setImage(templateImage, for: .normal)
clearButton.setImage(templateImage, for: .highlighted)
clearButton.tintColor = .white
}
}
Use below lines of code. If rightView is there clear button is not showing.
self.txtField.rightView = nil
self.txtField.rightViewMode = .never
self.txtField.clearButtonMode = UITextField.ViewMode.always
On Xcode Version 8.1 (8B62) it can be done directly in Attributes Inspector. Select the textField and then choose the appropriate option from Clear Button drop down box, which is located in Attributes Inspector.

Resources