iOS NSAttributedString on UIButton
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
NSAttributedString on UIButton
I found the Answer by struggling few days. And it is quite easy.
guard
let font1 = UIFont(name: "HelveticaNeue-Bold", size: 22),
let font2 = UIFont(name: "HelveticaNeue-Medium", size: 22) else { return }
let dict1:[String:Any] = [
// NSUnderlineStyleAttributeName:NSUnderlineStyle.styleSingle.rawValue,
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style,
NSForegroundColorAttributeName: UIColor.white
]
let dict2:[String:Any] = [
// NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue,
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style,
NSForegroundColorAttributeName: UIColor.white,
// NSFontAttributeName: UIFont.boldSystemFont(ofSize: 20)
]
let dict3:[String:Any] = [
// NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue,
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style,
NSForegroundColorAttributeName: UIColor.white
]
let dict4:[String:Any] = [
// NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue,
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style,
NSForegroundColorAttributeName: UIColor.white
]
let attString = NSMutableAttributedString()
attString.append(NSAttributedString(string: "Call to", attributes: dict1))
attString.append(NSAttributedString(string: " 2222555 ", attributes: dict2))
attString.append(NSAttributedString(string: " To Book Your Skip ", attributes: dict3))
attString.append(NSAttributedString(string: "NOW", attributes: dict4))
btnCall.setAttributedTitle(attString, for: .normal)
And its Working perfectly as expected.
Issues with NSAttributedString and Button
You are setting NSAttributedStringKey.strokeColor
, but you are not setting NSAttributedStringKey.strokeWidth
. That's why you don't get the desired result.
If it's not present, I guess (and it makes total sense) it's the same at setting the .strokeWidth
to 0, which is stated by the documentation "doing nothing":
Specify 0 (the default) for no additional changes
I got same result by setting it to 0 or not setting it at all.
Sample test code:
let str = "Hello !"
let attributedString = NSMutableAttributedString.init(string: str,
attributes: [.font: UIFont.systemFont(ofSize: 40),
.foregroundColor: UIColor.white])
let label1 = UILabel(frame: CGRect(x: 30, y: 40, width: 200, height: 50))
label1.backgroundColor = .lightGray
label1.attributedText = attributedString
let label2 = UILabel(frame: CGRect(x: 30, y: 95, width: 200, height: 50))
label2.backgroundColor = .lightGray
label2.attributedText = attributedString
let label3 = UILabel(frame: CGRect(x: 30, y: 150, width: 200, height: 50))
label3.backgroundColor = .lightGray
label3.attributedText = attributedString
let label4 = UILabel(frame: CGRect(x: 30, y: 205, width: 200, height: 50))
label4.backgroundColor = .lightGray
label4.attributedText = attributedString
attributedString.addAttributes([NSAttributedStringKey.strokeColor: UIColor.red],
range: NSRange.init(location: 0, length: attributedString.string.utf16.count))
label2.attributedText = attributedString
print("Only Stroke Color:\n\(attributedString)")
attributedString.addAttributes([NSAttributedStringKey.strokeWidth: 0],
range: NSRange.init(location: 0, length: attributedString.string.utf16.count))
label3.attributedText = attributedString
print("Stroke Color + Width set to 0:\n\(attributedString)")
attributedString.addAttributes([NSAttributedStringKey.strokeWidth: -4],
range: NSRange.init(location: 0, length: attributedString.string.utf16.count))
label4.attributedText = attributedString
print("Stroke Color + Width set to -4:\n\(attributedString)")
self.view.addSubview(label1)
self.view.addSubview(label2)
self.view.addSubview(label3)
self.view.addSubview(label4)
Log output:
$>Only Stroke Color:
Hello !{
NSColor = "UIExtendedGrayColorSpace 1 1";
NSFont = "<UICTFont: 0x7f8973e11120> font-family: \".SFUIDisplay\"; font-weight: normal; font-style: normal; font-size: 40.00pt";
NSStrokeColor = "UIExtendedSRGBColorSpace 1 0 0 1";
}
$>Stroke Color + Width set to 0:
Hello !{
NSColor = "UIExtendedGrayColorSpace 1 1";
NSFont = "<UICTFont: 0x7f8973e11120> font-family: \".SFUIDisplay\"; font-weight: normal; font-style: normal; font-size: 40.00pt";
NSStrokeColor = "UIExtendedSRGBColorSpace 1 0 0 1";
NSStrokeWidth = 0;
}
$>Stroke Color + Width set to -4:
Hello !{
NSColor = "UIExtendedGrayColorSpace 1 1";
NSFont = "<UICTFont: 0x7f8973e11120> font-family: \".SFUIDisplay\"; font-weight: normal; font-style: normal; font-size: 40.00pt";
NSStrokeColor = "UIExtendedSRGBColorSpace 1 0 0 1";
NSStrokeWidth = "-4";
}
Rendering:
Multiline NSAttributed String as UIButton Title
You can do it this way:
let dict1 = [NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle.rawValue]
let attString = NSMutableAttributedString()
attString.appendAttributedString(NSAttributedString(string: "Patient Name\n", attributes: dict1))
attString.appendAttributedString(NSAttributedString(string: "click for patient info", attributes: nil))
startVisitButton.setAttributedTitle(attString, forState: .Normal)
startVisitButton.titleLabel?.numberOfLines = 0
startVisitButton.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
And result will be:
How to center attributed title in UIButton
This is because the text is an attributed String, you will need to align the text after it has been set.
Solution for you will be:
aButton.setAttributedTitle(title, for: .normal)
aButton.titleLabel?.textAlignment = .center
By setting attributed String, instead of String, you are clearing all the button's text property.
Nicer solution will be to add alignment attribute into the attributed String
Programmatically change attributed title of UIButton
Partially you have the answer.
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[_ deleteButton attributedTitleForState:UIControlStateNormal]];
[attributedString replaceCharactersInRange:NSMakeRange(0, attributedString.length) withString:@"Your new string"];
[_ deleteButton setAttributedTitle:attributedString forState:UIControlStateNormal];
Instead of creating NSAttributedString
create NSMutableAttributedString
then you can just set the string like this.
How do you set an Attributed Title Color for State in Swift
// create the button
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.backgroundColor = UIColor.yellowColor()
// set the attributed title for different states
// .Selected
let mySelectedAttributedTitle = NSAttributedString(string: "Click Here",
attributes: [NSForegroundColorAttributeName : UIColor.greenColor()])
button.setAttributedTitle(mySelectedAttributedTitle, forState: .Selected)
// .Normal
let myNormalAttributedTitle = NSAttributedString(string: "Click Here",
attributes: [NSForegroundColorAttributeName : UIColor.blueColor()])
button.setAttributedTitle(myNormalAttributedTitle, forState: .Normal)
Related Topics
Embed a Uiviewcontroller in a Navigationcontroller Using Segues
Return Value from Completion Handler - Swift
Swiftui Modal Presentation Works Only Once from Navigationbaritems
Swiftui: Set Status Bar Color for a Specific View
Storyboard Segues Causing Memory Leaks
Uitextfield -Webview No Longer Supported
Fbsdkloginmanager Loginwithpublishpermissions Always Returns Iscancelled=Yes
Split View Controller Must Be Root View Controller
Storing Uicolor Object in Core Data
Hide Device Volume Hud View While Adjusitng Volume with Mpvolumeview Slider
Code Signing Error: Application Failed Codesign Verification
Multiple Locations on Map (Using Mkmapitem and Clgeocoder)
How to Convert an Uiimage to Grayscale in Swift Using Cifilter
Detect If the Application in Background or Foreground in Swift