UIButton textLabel with different fonts - ios

Is there a way to have a UIButton with two different font sizes in its textLabel? Natively?
I don't want to have a UILabel on top.

You can do this in interface builder. This GIF will show you how to increase the size of one section of the text and perhaps change its font.
To do this in code:
NSString *fullString = #"This bit's plain. This bit's bigger";
NSRange rangeOfPlainBit = [fullString rangeOfString:#"This bit's plain."];
NSRange rangeOfBigBit = [fullString rangeOfString:#"This bit's bigger"];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:fullString];
[attributedText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"My-font" size:15.0],
NSForegroundColorAttributeName: [UIColor whiteColor]}
range:rangeOfPlainBit];
[attributedText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"My-font" size:25.0],
NSForegroundColorAttributeName: [UIColor whiteColor]}
range:rangeOfBigBit];
[self.myButton setAttributedTitle:attributedText forState:UIControlStateNormal];

SWIFT 3
func customizeButtonFont(fullText: String, mainText: String, creditsText: String, button: UIButton) {
let fontBig = UIFont(name:"SFUIDisplay-Medium", size: 16.0)
let fontSmall = UIFont(name:"SFUIDisplay-Light", size: 14.0)
let attributedString = NSMutableAttributedString(string: fullText, attributes: nil)
let bigRange = (attributedString.string as NSString).range(of: mainText)
let creditsRange = (attributedString.string as NSString).range(of: creditsText)
attributedString.setAttributes([NSAttributedStringKey.font: fontBig, NSAttributedStringKey.foregroundColor: UIColor.white], range: bigRange)
attributedString.setAttributes([NSAttributedStringKey.font: fontSmall, NSAttributedStringKey.foregroundColor: UIColor.white], range: creditsRange)
button.setAttributedTitle(attributedString, for: .normal)
}

just change the font size for the title.
swift:
button.titleLabel.font = UIFont.systemFontOfSize(FONTSIZE)

Related

AsyncDisplayKit ASButtonNode setTitle not work

I use AsyncDisplayKit write button , and use ASButtonNode , but I can't set title when I use - (void)setAttributedTitle:(NSAttributedString *)title forState:(ASButtonState)state . It can respond action, but without title. Am I worry or something else need set ?
Here is code :
NSDictionary *placeholderAttrs = #{NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-LightItalic" size:14.0f] , NSForegroundColorAttributeName: [UIColor greenColor] };
ASButtonNode *button = [[ASButtonNode alloc] init];
[button setAttributedTitle:[[NSAttributedString alloc] initWithString:#"button" attributes:placeholderAttrs] forState:ASButtonStateNormal];
[button addTarget:self action:#selector(action:) forControlEvents:ASControlNodeEventTouchUpInside];
[button setFrame:CGRectMake(20, 20, 100, 44)];
button.backgroundColor = [UIColor redColor];
button.titleNode.displaysAsynchronously = NO;
[self.view addSubnode:button];
Thanks.
#leo, It looks like you may just need to measure your ASButtonNode before adding it to your view.
[button measure:...];
Please reference into this topic here Add custom Button with AsyncDisplayKit
Basiclly, ASTextNode will be used as button, also below func example aim to set title, color, font-weight and color (in Swift)
func configureTextNode(text: String, size: CGFloat, frame : CGRect = CGRectMake(0,0,0,0), bold: Bool = false, color: UIColor = UIColor.whiteColor(), textAlignment: NSTextAlignment = .Left) -> ASTextNode {
let textNode = ASTextNode()
let range = NSMakeRange(0, text.characters.count)
// Set String
let mutableString = NSMutableAttributedString(string: text) // Set string
// Set size and font-weight
let fontSize = bold ? UIFont.boldSystemFontOfSize(size) : UIFont.systemFontOfSize(size)
mutableString.addAttribute(NSFontAttributeName, value: fontSize, range: range)
// Set text color
mutableString.addAttribute(NSForegroundColorAttributeName, value: color, range: range)
// Set alignment
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = textAlignment
mutableString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: range)
// Add attributes into node
textNode.attributedString = mutableString
// Node Frame
textNode.frame = frame
return textNode
}
you can use this code
fileprivate var noteButtonNode : ASButtonNode = ASButtonNode()
addSubnode(noteButtonNode)
let attributedTitle : NSAttributedString = NSAttributedString(
string: "Your_Text",
attributes: [
NSFontAttributeName: UIFont.init(name: Fonts.Your_Font, size: 16)!,
NSForegroundColorAttributeName: Colors.Your_Color
])
noteButtonNode.setAttributedTitle(attributedTitle, for: ASControlState())

Multiple Fonts used for Navigation Bar Titles

Wondering if this is possible...for simplicity's sake lets say I have an app that uses a navigation controller and the app has two sections "News" and "Sports".
I set a custom font in the navigation controller and that effects both the News and Sports titles. Is there a way to override that initial font setting and use a separate font for just the Sports title? So effectively I'd be using one font for the News title and a different one for the Sports title.
Thanks so much.
Put this in your viewDidLoad()
titleLabel = UILabel(frame: CGRectMake(0, 0, 200, 44))
titleLabel.text = "Discover"
titleLabel.font = UIFont(name: "SFUIDisplay-Light", size: 21)
titleLabel.textColor = UIColor.whiteColor()
titleLabel.textAlignment = NSTextAlignment.Center
self.navigationItem.titleView = titleLabel
Try with This. Its work in Obj c.
for (UIView *view in self.navigationItem.titleView.subviews) {
[view removeFromSuperview];
}
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, 200, 44)];
self.navigationItem.titleView.backgroundColor = [UIColor redColor];
self.navigationItem.titleView = textView;
NSString *newsTitle = #"News Title";
NSString *sportTtle = #"Sport Title";
NSString *title = [NSString stringWithFormat:#"%# %#", newsTitle,sportTtle];
textView.text = title;
UIColor *color = [UIColor redColor];
UIFont *font = [UIFont fontWithName:#"Arial" size:20.0];
NSDictionary *attrs = #{NSForegroundColorAttributeName : color,NSFontAttributeName:font};//
NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc] initWithAttributedString:textView.attributedText];
[attrStr addAttributes:attrs range:[textView.text rangeOfString:sportTtle]];
textView.attributedText = attrStr;
Swift Code:
func customizeNavigationTitle(){
let textView :UITextView = UITextView();
textView.frame = CGRectMake(0, 0, 200, 44)
self.navigationItem.titleView = textView;
let newsTitle:NSString = "News Title"
let sportTtle:NSString = "Sport Title"
var title = String(format: "%#%#", newsTitle,sportTtle)
textView.text = title;
var color:UIColor = UIColor.redColor();
var font:UIFont = UIFont(name: "Arial", size: 16)!
//Helvetica Neue
var attrs:AnyObject = [ NSForegroundColorAttributeName:color ,NSFontAttributeName: font]
var attrStr = NSMutableAttributedString(string:title, attributes:attrs as! [String : AnyObject]) as! NSMutableAttributedString;
var range = textView.text.rangeOfString(sportTtle as String)!
var attrSports = [ NSForegroundColorAttributeName:color ,NSFontAttributeName: font]
var textRange = NSRange(location:newsTitle.length , length: sportTtle.length)
attrStr.addAttribute(NSForegroundColorAttributeName, value: UIColor .greenColor(), range: textRange)
textView.attributedText = attrStr;
}

Attributed Text Center Alignment

I have tried everything but cannot seem to center this text. Can someone please tell me where the error is.
NSMutableParagraphStyle *paragraphStyle = NSMutableParagraphStyle.new;
paragraphStyle.alignment = NSTextAlignmentCenter;
label.attributedText = [[NSAttributedString alloc] initWithString:cell.EventTitle.text attributes:#{NSForegroundColorAttributeName : [UIColor whiteColor],NSParagraphStyleAttributeName:paragraphStyle,NSBaselineOffsetAttributeName : #0,NSFontAttributeName : [UIFont fontWithName:#"BrandonGrotesque-Black" size:34]}];
In Swift 5
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = .center
textView.attributedText = NSAttributedString(string: "String",
attributes: [.paragraphStyle: paragraph])
In Swift-4
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = .center
let attributes: [NSAttributedString.Key : Any] = [NSAttributedString.Key.paragraphStyle: paragraph]
let attrString = NSAttributedString(string:"string", attributes: attributes)
textView.attributedText = attrString
In Swift-3
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = .center
let attributes: [String : Any] = [NSParagraphStyleAttributeName: paragraph]
let attrString = NSAttributedString(string:"string", attributes: attributes)
textView.attributedText = attrString
You can set the center alignment using this. Remember to set range.
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setAlignment:NSTextAlignmentCenter];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [string length])];
In Swift 4
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = .center
textView.attributedText = NSAttributedString(string: "string",
attributes: [.paragraphStyle: paragraph])
Another way:
Swift:
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let attributedString = NSAttributedString(string: "This will be centered.", attributes: [ NSAttributedString.Key.paragraphStyle: paragraphStyle])
Obj-C:
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.alignment = NSTextAlignmentCenter;
NSAttributedString *attributedString = [NSAttributedString.alloc initWithString:#"This will be centered."
attributes: #{NSParagraphStyleAttributeName:paragraphStyle}];
Swift 4+
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.center
// Swift 4.2++
let attributedString = NSMutableAttributedString(string: "Your String", attributes: [NSAttributedString.Key.paragraphStyle:paragraphStyle])
// Swift 4.1--
let attributedString = NSMutableAttributedString(string: "Your String", attributes: [NSAttributedStringKey.paragraphStyle:paragraphStyle])
let yourLabel = UILabel()
yourLabel.attributedText = attributedString
Objective-C
NSString *string = #"Your String";
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentCenter;
NSMutableAttributedString * attributedString = [[NSMutableAttributedString alloc] initWithString:string attributes: #{NSParagraphStyleAttributeName:paragraphStyle}];
UILabel *label = [[UILabel alloc] init];
label.attributedText = attributedString;
In Swift
let titleString = "title here"
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .Center
let attributedString = NSAttributedString(
string: titleString,
attributes: [NSParagraphStyleAttributeName: paragraphStyle]
)
titleAttributedLabel.attributedText = attributedString
Swift4
let attributedString = NSMutableAttributedString(string: "Example text that is centered using a paragraph style. With the ability to change the width between lines.", attributes: [NSAttributedStringKey.font: GothamFont.medium(with: 14)])
let myParagraphStyle = NSMutableParagraphStyle()
myParagraphStyle.alignment = .center // center the text
myParagraphStyle.lineSpacing = 14 //Change spacing between lines
myParagraphStyle.paragraphSpacing = 38 //Change space between paragraphs
attributedString.addAttributes([.paragraphStyle: myParagraphStyle], range: NSRange(location: 0, length: attributedString.length))
helper method based on the helpful answers above
public extension NSAttributedString
{
var centered: NSAttributedString
{
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = .center
let m = NSMutableAttributedString(attributedString: self)
m.addAttribute(.paragraphStyle, value: paragraph, range: NSMakeRange(0, length))
return m
}
}
in case you want the Is dotted and Ts crossed el verbositas version
var centered: NSAttributedString {
let paragraphStyle: NSMutableParagraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.center
let attributedString = NSMutableAttributedString(attributedString: self)
attributedString.addAttributes([NSAttributedString.Key.paragraphStyle : paragraphStyle],
range: NSRange(location: 0, length: attributedString.length))
return attributedString
}
To do it in Swift 2.x
let attributeString = NSMutableAttributedString(string: "text")
style.alignment = .Center
attributeString.addAttribute(NSParagraphStyleAttributeName, value: style, range: range)
Sometimes when text is in Arabic or other right align languages then when doing alignment Justified, last line text ends at left side. for this we can add baseWritingDirection below is sample code
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .justified
paragraphStyle.baseWritingDirection = .rightToLeft
attribute.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:range)
txtView.attributedText = attribute
Set line breakmode, if you set attributed text on UIButton.
Swift 5
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = .center
paragraph.lineBreakMode = .byClipping
Objective-C
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.alignment = NSTextAlignmentCenter;
style.lineBreakMode = NSLineBreakByClipping;
This works for me
label.textAlignment = .center

Changing UITextField Placeholder font

I'm changing the placeholder text color with the following code, but when I try to add NSFontAttribute I get the compiler error "too many arguments to method call, expect 2 have 3"
UIColor *color = [UIColor blackColor];
_nameField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Your Name" attributes:#{NSForegroundColorAttributeName: color},#{NSFontAttributeName:#"Roboto-Bold"}];
This Works Fine:
UIColor *color = [UIColor blackColor];
_nameField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Your Name" attributes:#{NSForegroundColorAttributeName: color}];
Objective-C:
UIColor *color = [UIColor blackColor];
someUITextField.attributedPlaceholder =
[[NSAttributedString alloc] initWithString:#"Placeholder Text"
attributes:#{
NSForegroundColorAttributeName: color,
NSFontAttributeName : [UIFont fontWithName:#"Roboto-Bold" size:17.0]
}
];
(There are no brackets between literal dictionary key-value pairs.)
Swift:
let attributes = [
NSForegroundColorAttributeName: UIColor.blackColor(),
NSFontAttributeName : UIFont(name: "Roboto-Bold", size: 17)! // Note the !
]
someUITextField.attributedPlaceholder = NSAttributedString(string: "Placeholder Text", attributes:attributes)
Update for Swift 4.x:
textField.attributedPlaceholder = NSAttributedString(string: "Placeholder Text", attributes: [
.foregroundColor: UIColor.lightGray,
.font: UIFont.boldSystemFont(ofSize: 14.0)
])
For the convenience of swift people:
someTextField.attributedPlaceholder = NSAttributedString(string: "someString",
attributes:[NSForegroundColorAttributeName: UIColor.lightGrayColor(), NSFontAttributeName: PlaceHolderFont])
You should subclass UITextField, and override the method of:
- (void)drawPlaceholderInRect:(CGRect)rect;
Here is the implementation below:
- (void)drawPlaceholderInRect:(CGRect)rect {
NSDictionary *attributes = #{
NSForegroundColorAttributeName : [UIColor lightGrayColor],
NSFontAttributeName : [UIFont italicSystemFontOfSize:self.font.pointSize]
};
// center vertically
CGSize textSize = [self.placeholder sizeWithAttributes:attributes];
CGFloat hdif = rect.size.height - textSize.height;
hdif = MAX(0, hdif);
rect.origin.y += ceil(hdif/2.0);
[[self placeholder] drawInRect:rect withAttributes:attributes];
}
For more you can find click here
Appreciate #ddevaz answer.
UITextField Subclass solution
Above answer works perfect for UITextField. But when i use UITextField subclass and try to execute this method in it. Then its not working.
I found other solution only when you subclass UITextField. Override below method in your UITextField subclass and it will do job for you.
- (void) drawPlaceholderInRect:(CGRect)rect {
NSDictionary *attrDictionary = #{
NSForegroundColorAttributeName: [UIColor lightGrayColor],
NSFontAttributeName : [UIFont fontWithName:#"Menlo" size:17.0]
};
[[self placeholder] drawInRect:rect withAttributes:attrDictionary];
}
Working version for Swift 4
let attributes = [NSAttributedStringKey.foregroundColor: UIColor.black,
.font : UIFont.systemFont(ofSize: 14, weight: .regular)]
someTextfield.attributedPlaceholder = NSAttributedString(string: "Placeholder text", attributes:attributes)
Update for Swift 4
let attributes = [
NSAttributedStringKey.foregroundColor: .black,
NSAttributedStringKey.font : UIFont(name: "Your font name", size: 14)!
]
someTextfield.attributedPlaceholder = NSAttributedString(string: "Placeholder text", attributes:attributes)
Update for Swift 4.2 +
let attributes = [NSAttributedString.Key.foregroundColor: UIColor.black,
.font: UIFont.systemFont(ofSize: 14)]
searchTextField.attributedPlaceholder = NSAttributedString(string: "Placeholder text",
attributes: attributes)
Reference for more attribute Keys - NSAttributedString.Key
If you want to support both iOS 6 and previous versions then:
UIColor *placeholderColor = [UIColor lightTextColor];
UIFont *placeholderFont = [UIFont systemFontOfSize:[UIFont systemFontSize]];
if ([textField respondsToSelector:#selector(attributedPlaceholder)]) {
#ifdef __IPHONE_6_0
textField.attributedPlaceholder = [[NSAttributedString alloc]
initWithString:textField.placeholder attributes: // NOTE: textField.placeholder can't be nil
#{ NSForegroundColorAttributeName : placeholderColor,
NSFontAttributeName : placeholderFont }];
#endif
} else { // for pre-iOS6
[textField setValue:placeholderColor forKeyPath:#"_placeholderLabel.textColor"];
[textField setValue:placeholderFont forKeyPath:#"_placeholderLabel.font"];
}
You can use below code
First find name of system accepted font for your Custom font
for (NSString *familyName in [UIFont familyNames]) {
for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
NSLog(#"%#", fontName);
}
}
and then use below code make your placeholder with custom font
searchTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Where are you shopping?" attributes:#{NSFontAttributeName : font }];
Else there can be chance to get nil object[1] for font not found
let attributes: [NSAttributedStringKey : Any] = [NSAttributedStringKey.foregroundColor: UIColor.black,
NSAttributedStringKey.font: UIFont(name: "Menlo", size: 17.0) ?? UIFont.systemFont(ofSize: 17.0) ]
textField.attributedPlaceholder = NSAttributedString(string: "Placeholder Text", attributes: attributes)
Note: when we use UIFont(name: "Menlo", size: 17.0) method, if the font name can't get it in ios , so it will be nil, so we need to provide the default font. It was explained above.
You can use below code First find name of system accepted font for your Custom font
for (NSString *familyName in [UIFont familyNames]) {
for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
NSLog(#"%#", fontName);
}
}
Swift 4: Placeholder Color change using UITextField subclass
override func drawPlaceholder(in rect: CGRect) {
let color = UIColor(red: 210/255, green: 210/255, blue: 210/255, alpha: 1.0)
if (placeholder?.responds(to: #selector(NSString.draw(in:withAttributes:))))! {
let fontS = UIFont.systemFont(ofSize: 12)
let attributes = [NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.font: fontS] as [NSAttributedStringKey : Any]
let boundingRect: CGRect = placeholder!.boundingRect(with: rect.size, options: [], attributes: attributes, context: nil)
placeholder?.draw(at: CGPoint(x: 0, y: (rect.size.height / 2) - boundingRect.size.height / 2), withAttributes: attributes)
}
}
if you have problem same me. I solve by set Font because some time font can't change when set Font in stroryboard or set in self.emailTextField.placeholder .
self.emailTextField.font = UIFont(..custom you font....)
You can change the font size of the text and placeholder by simply doing this.
field.font = .systemFont(ofSize: 16)

iOS NSAttributedString on UIButton

I'm using iOS 6, so attributed strings should be easy to use, right? Well... not so much.
What I want to do:
Using a custom subclass of UIButton (it doesn't do anything custom to titleLabel), I'd like to have a multi-line, attributed title that is:
All caps (I realize that's not part of the attributes) on the first line
Bolded on the first line
Underlined on the first line
"Normal" weight on the second line
Non-underlined on the second line
Centered on both lines
I've been able to get #'s 1 through 5 so far (at least, I thought I did, but current testing is yielding errors with multi-line text), but when I tried to do something (anything!) to get the text to be centered, my app keeps crashing. When I try to get all 6 items working (through various methods), I get the following crash/error:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason:
'NSAttributedString invalid for autoresizing,
it must have a single spanning paragraph style
(or none) with a non-wrapping lineBreakMode.'
Based on what I've tried, it appears that I can have one of the following options, but not both:
A multi-line, centered label
An attributed label
I can live with one or the other if I must, but I can't believe that I can't have what seems to be a fairly straightforward concept.
Can someone please tell me what I've got wrong?
Here's the last iteration of the code I'm trying:
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSTextAlignmentCenter];
[style setLineBreakMode:NSLineBreakByWordWrapping];
UIFont *font1 = [UIFont fontWithName:#"HelveticaNeue-Medium" size:20.0f];
UIFont *font2 = [UIFont fontWithName:#"HelveticaNeue-Light" size:20.0f];
NSDictionary *dict1 = #{NSUnderlineStyleAttributeName:#(NSUnderlineStyleSingle),
NSFontAttributeName:font1};
NSDictionary *dict2 = #{NSUnderlineStyleAttributeName:#(NSUnderlineStyleNone),
NSFontAttributeName:font2};
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:#"LINE 1\n" attributes:dict1]];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:#"line 2" attributes:dict2]];
[[self buttonToStyle] setAttributedTitle:attString forState:UIControlStateNormal];
[[[self buttonToStyle] titleLabel] setNumberOfLines:0];
[[[self buttonToStyle] titleLabel] setLineBreakMode:NSLineBreakByWordWrapping];
It looks to me like you forgot in your code to use the "style" object that you set up.. you just instantiated it. You should modify your code to look like this:
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSTextAlignmentCenter];
[style setLineBreakMode:NSLineBreakByWordWrapping];
UIFont *font1 = [UIFont fontWithName:#"HelveticaNeue-Medium" size:20.0f];
UIFont *font2 = [UIFont fontWithName:#"HelveticaNeue-Light" size:20.0f];
NSDictionary *dict1 = #{NSUnderlineStyleAttributeName:#(NSUnderlineStyleSingle),
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style}; // Added line
NSDictionary *dict2 = #{NSUnderlineStyleAttributeName:#(NSUnderlineStyleNone),
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style}; // Added line
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:#"LINE 1\n" attributes:dict1]];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:#"line 2" attributes:dict2]];
[self.resolveButton setAttributedTitle:attString forState:UIControlStateNormal];
[[self.resolveButton titleLabel] setNumberOfLines:0];
[[self.resolveButton titleLabel] setLineBreakMode:NSLineBreakByWordWrapping];
Note that I only added the lines that define the NSParagraphStyleAttributeName.. everything else is the same.. and this is what I get for the button:
And here it is in Swift 3.0
let style = NSMutableParagraphStyle()
style.alignment = .center
style.lineBreakMode = .byWordWrapping
guard
let font1 = UIFont(name: "HelveticaNeue-Medium", size: 20),
let font2 = UIFont(name: "HelveticaNeue-Light", size: 20) else { return }
let dict1:[String:Any] = [
NSUnderlineStyleAttributeName:NSUnderlineStyle.styleSingle.rawValue,
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style
]
let dict2:[String:Any] = [
NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue,
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style
]
let attString = NSMutableAttributedString()
attString.append(NSAttributedString(string: "LINE 1", attributes: dict1))
attString.append(NSAttributedString(string: "line 2", attributes: dict2))
button.setAttributedTitle(attString, for: .normal)
button.titleLabel?.numberOfLines = 0
button.titleLabel?.lineBreakMode = .byWordWrapping
With Swift 5.1 and iOS 13.1, you can use the UIButton subclass implementation below in order to solve your problem:
import UIKit
class CustomButton: UIButton {
required init(title: String, subtitle: String) {
super.init(frame: CGRect.zero)
let style = NSMutableParagraphStyle()
style.alignment = NSTextAlignment.center
style.lineBreakMode = NSLineBreakMode.byWordWrapping
let titleAttributes: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.foregroundColor: UIColor.label,
NSAttributedString.Key.underlineStyle : NSUnderlineStyle.single.rawValue,
NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.largeTitle),
NSAttributedString.Key.paragraphStyle : style
]
let subtitleAttributes = [
NSAttributedString.Key.foregroundColor: UIColor.label,
NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body),
NSAttributedString.Key.paragraphStyle : style
]
let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes)
attributedString.append(NSAttributedString(string: "\n"))
attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes))
setAttributedTitle(attributedString, for: UIControl.State.normal)
titleLabel?.numberOfLines = 0
titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Usage:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = CustomButton(title: "Title", subtitle: "Subtitle")
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
}
}
As an alternative if you really need a button of type system, you may use the following code:
import UIKit
extension UIButton {
static func customSystemButton(title: String, subtitle: String) -> UIButton {
let style = NSMutableParagraphStyle()
style.alignment = NSTextAlignment.center
style.lineBreakMode = NSLineBreakMode.byWordWrapping
let titleAttributes: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.underlineStyle : NSUnderlineStyle.single.rawValue,
NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.largeTitle),
NSAttributedString.Key.paragraphStyle : style
]
let subtitleAttributes = [
NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body),
NSAttributedString.Key.paragraphStyle : style
]
let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes)
attributedString.append(NSAttributedString(string: "\n"))
attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes))
let button = UIButton(type: UIButton.ButtonType.system)
button.setAttributedTitle(attributedString, for: UIControl.State.normal)
button.titleLabel?.numberOfLines = 0
button.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
return button
}
}
Usage:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton.customSystemButton(title: "Title", subtitle: "Subtitle")
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
}
}
The two screen shots below show the result display for the UIButton subclass (on the left) and for the system type button (on the right):
Two line UIButton with NSAttributedString title in Swift 5.1:
func customizeSubscribeButton() {
subscribeButton.titleLabel?.numberOfLines = 2
let title = NSMutableAttributedString()
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let part1 = NSAttributedString(string: "SUBSCRIBE FOR 12 MONTH\n",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.white,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 24, weight: .semibold),
NSAttributedString.Key.paragraphStyle: paragraphStyle])
let part2 = NSAttributedString(string: "999.00 RUB ECONOMY 85%",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.white,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12, weight: .light),
NSAttributedString.Key.paragraphStyle: paragraphStyle])
title.append(part1)
title.append(part2)
subscribeButton.setAttributedTitle(title, for: .normal)
}

Resources