How to Set an Attributed Title Color for State in Swift

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)

Title color of UIButton won't change on highlighted/selected but background color will

setTitleColor doesn't have any effect when the title is an attributed string. Either use a plain NSString or call setAttributedTitle again after applying the desired color to the attributed string.

UIButton Change Title Color Partially

Use NSMutableAttributedString for this purpose

private let signUpButton = UIButton().then {
// Creating gray text part
let grayButtonText = NSAttributedString(string: "FirstPart", attributes: [.font: UIFont.systemFont(ofSize: 12), .foregroundColor: UIColor.gray ])
// Creating black text part
let blackButtonText = NSAttributedString(string: "SecondPart", attributes: [.font: UIFont.systemFont(ofSize: 12), .foregroundColor: UIColor.black ])

// Merging two parts together
let buttonTitle = NSMutableAttributedString(attributedString: grayButtonText)
buttonTitle.append(blackButtonText)

// Set it as a title for ".normal" state
$0.setAttributedTitle(buttonTitle, for: .normal)
}

How to set the title text color of UIButton?

You have to use func setTitleColor(_ color: UIColor?, for state: UIControl.State) the same way you set the actual title text. Docs

isbeauty.setTitleColor(UIColorFromRGB("F21B3F"), for: .normal)

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:

Sample Image

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

iOS button title color won't change

Because your button will turn back to UIControlState.Normal after you touch it, it become .Highlighted, then .Normal

You should set
sender.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Selected)

to

sender.setTitleColor(UIColor.whiteColor(), forState: UIControlState. Normal)

or, just set it for all the states since u did a check for color like

sender.setTitleColor(UIColor.whiteColor(), forState: [.Normal,.Selected,.Highlighted])

*Edit: Above doesn't work, can use NSAttributedString instead

if self.loginButton.backgroundColor == UIColor.blackColor() {
let tittle = NSAttributedString(string: "Login", attributes: [NSForegroundColorAttributeName: UIColor.blackColor()])
loginButton.setAttributedTitle(tittle, forState: .Normal)
loginButton.backgroundColor = UIColor.whiteColor()
} else {
let tittle = NSAttributedString(string: "Login", attributes: [NSForegroundColorAttributeName: UIColor.whiteColor()])
loginButton.setAttributedTitle(tittle, forState: .Normal)
loginButton.backgroundColor = UIColor.blackColor()
}

Creating UIButton attributed title based on its original plain text state

Got this to work finally. Turns out that there are several properties of a plain text UIButton that are in several places. Some have helper methods to retrieve directly from the UIButton, some do not.

  • Font: self.titleLabel.font (no helper method)
  • Colour: [self titleColorForState:state]
  • Text: [self titleForState:state]
  • Attributed Text: [self attributedTitleForState]

And a plain text UIButton does not have any text alignment by default, since that's controlled by content horizontal alignment.

As such, I changed up my helper methods (the first is identical, but I had to change the second):

+ (NSMutableAttributedString*)attributedStringWithTitle:(NSString*)title fromExistingAttributedString:(NSAttributedString*)attributedString
{
NSDictionary *attributes = [attributedString attributesAtIndex:0 effectiveRange:NULL];
return [[NSMutableAttributedString alloc] initWithString:title attributes:attributes];
}

+ (NSMutableAttributedString*)attributedStringWithTitle:(NSString*)title font:(UIFont*)font color:(UIColor*)color
{
NSMutableAttributedString* mutableTitle = [[NSMutableAttributedString alloc] initWithString:title];
[mutableTitle addAttribute:NSFontAttributeName value:font range:[mutableTitle fullRange]];
[mutableTitle addAttribute:NSForegroundColorAttributeName value:color range:[mutableTitle fullRange]];
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[mutableTitle addAttribute:NSParagraphStyleAttributeName value:style range:[mutableTitle fullRange]];
return mutableTitle;
}

And I've implemented it like this:

- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state
{
NSMutableAttributedString* mutableTitle = [title mutableCopy];
[mutableTitle addAttributes:@{NSKernAttributeName: @(kDefaultKerning)} range:[mutableTitle fullRange]];
[super setAttributedTitle:mutableTitle forState:state];
[self setNeedsDisplay];
}

- (void)setTitle:(NSString *)title forState:(UIControlState)state
{
NSMutableAttributedString* mutableTitle;
if ([self attributedTitleForState:state]) {
mutableTitle = [NSMutableAttributedString attributedStringWithTitle:title fromExistingAttributedString:[self attributedTitleForState:state]];
} else {
mutableTitle = [NSMutableAttributedString attributedStringWithTitle:title font:self.titleLabel.font color:[self titleColorForState:state]];
}
[self setAttributedTitle:mutableTitle forState:state];
}


Related Topics



Leave a reply



Submit