NSButton how to color the text
Asked Answered
B

13

34

on OSX I have an NSButton with a pretty dark image and unfortunately it is not possible to change the color using the attributes inspector. See picture the big black button, the text is Go.

enter image description here

Any clues for a possibility to change the text color? I looked in to the NSButton class but there is no method to do that. I´m aware that I could make the image with white font but that is not what I want to do.

Greetings from Switzerland, Ronald Hofmann --- 

Battista answered 28/10, 2012 at 15:5 Comment(5)
No not yet, wait a minute :) Same thing no setColor in NSAttributedString.Battista
- [NSMutableAttributedString addAttribute:NSForegroundColorAttributeName value:[NSColor colorWithSRGBRed:1.0 green:0.0 blue:0.0 alpha:0.0] range:NSMakeRange(0, string.length)];Potoroo
Very nice H2CO3, thanks for your effort. Go is now white. But now Go is white and small on the left, outside the Button. Can´t paste an image here unfortunately ;( I loked for Position without success. I don´t understand why font size and position changes? Is that correct? I assumed that would remain the same as before. I just wanted to change the font color.Battista
Not really an answer to the problem you are experiencing but why not just add whatever text you want to the image you initialize the button with? Just an input...Copulation
Yes, that is definitely a solution. On the other hand I'm curious and want to know how things work.Battista
B
50

Here is two other solutions: http://denis-druz.okis.ru/news.534557.Text-Color-in-NSButton.html

solution 1:

-(void)awakeFromNib
{
    NSColor *color = [NSColor greenColor];
    NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[button attributedTitle]];
    NSRange titleRange = NSMakeRange(0, [colorTitle length]);
    [colorTitle addAttribute:NSForegroundColorAttributeName value:color range:titleRange];
    [button setAttributedTitle:colorTitle];
}

solution 2:

in *.m file:

- (void)setButtonTitleFor:(NSButton*)button toString:(NSString*)title withColor:(NSColor*)color
{
    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
    [style setAlignment:NSCenterTextAlignment];
    NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:color, NSForegroundColorAttributeName, style, NSParagraphStyleAttributeName, nil];
    NSAttributedString *attrString = [[NSAttributedString alloc]initWithString:title attributes:attrsDictionary];
    [button setAttributedTitle:attrString];
}

-(void)awakeFromNib
{
    NSString *title = @"+Add page";
    NSColor *color = [NSColor greenColor];
    [self setButtonTitleFor:button toString:title withColor:color];
}
Bedfellow answered 4/7, 2013 at 14:7 Comment(3)
Please edit your answer and format the code to make it readable.Oren
please format this properly. This way it's easier for other user to read your postBanian
on click button text gets removed, osx 10.11, xcode 8.1Divertissement
F
16

My solution:

.h

IB_DESIGNABLE
@interface DVButton : NSButton

@property (nonatomic, strong) IBInspectable NSColor *BGColor;
@property (nonatomic, strong) IBInspectable NSColor *TextColor;

@end


.m

@implementation DVButton

- (void)awakeFromNib
{
    if (self.TextColor)
    {
        NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
        [style setAlignment:NSCenterTextAlignment];
        NSDictionary *attrsDictionary  = [NSDictionary dictionaryWithObjectsAndKeys:
                                          self.TextColor, NSForegroundColorAttributeName,
                                          self.font, NSFontAttributeName,
                                          style, NSParagraphStyleAttributeName, nil];
        NSAttributedString *attrString = [[NSAttributedString alloc]initWithString:self.title attributes:attrsDictionary];
        [self setAttributedTitle:attrString];
    }
}


- (void)drawRect:(NSRect)dirtyRect
{
    if (self.BGColor)
    {
        // add a background colour
        [self.BGColor setFill];
        NSRectFill(dirtyRect);
    }

    [super drawRect:dirtyRect];
}

@end

enter image description here

And here’s a Swift 3 version:

import Cocoa

@IBDesignable
class DVButton: NSButton
{
    @IBInspectable var bgColor: NSColor?
    @IBInspectable var textColor: NSColor?

    override func awakeFromNib()
    {
        if let textColor = textColor, let font = font
        {
            let style = NSMutableParagraphStyle()
            style.alignment = .center

            let attributes =
            [
                NSForegroundColorAttributeName: textColor,
                NSFontAttributeName: font,
                NSParagraphStyleAttributeName: style
            ] as [String : Any]

            let attributedTitle = NSAttributedString(string: title, attributes: attributes)
            self.attributedTitle = attributedTitle
        }
    }

    override func draw(_ dirtyRect: NSRect)
    {
        if let bgColor = bgColor
        {
            bgColor.setFill()
            NSRectFill(dirtyRect)
        }

        super.draw(dirtyRect)
    }

}

and Swift 4.0 version:

import Cocoa

@IBDesignable
 class Button: NSButton
{
    @IBInspectable var bgColor: NSColor?
    @IBInspectable var textColor: NSColor?

    override func awakeFromNib()
    {
        if let textColor = textColor, let font = font
        {
            let style = NSMutableParagraphStyle()
            style.alignment = .center

            let attributes =
            [
                NSAttributedStringKey.foregroundColor: textColor,
                NSAttributedStringKey.font: font,
                NSAttributedStringKey.paragraphStyle: style
             ] as [NSAttributedStringKey : Any]

            let attributedTitle = NSAttributedString(string: title, attributes: attributes)
            self.attributedTitle = attributedTitle
        }
    }

    override func draw(_ dirtyRect: NSRect)
    {
        if let bgColor = bgColor
        {
            bgColor.setFill()
            __NSRectFill(dirtyRect)
        }

        super.draw(dirtyRect)
    }
}
Feint answered 16/11, 2015 at 15:52 Comment(2)
do you think you could add a rounded corner to this solution? :)Reducer
@Reducer just replace NSRectFill(dirtyRect) with: let rect = NSMakeRect(0, 0, bounds.width, bounds.height) let rectanglePath = NSBezierPath( roundedRect: rect, xRadius: 3, yRadius: 3) rectanglePath.fill()Zebulun
O
9

This is how I get it done in Swift 4

 @IBOutlet weak var myButton: NSButton!

 // create the attributed string
 let myString = "My Button Title"
 let myAttribute = [ NSAttributedStringKey.foregroundColor: NSColor.blue ]
 let myAttrString = NSAttributedString(string: myString, attributes: myAttribute)
 // assign it to the button
 myButton.attributedTitle = myAttrString
Ogre answered 24/1, 2018 at 8:11 Comment(0)
F
8

Apple have code for setting the text colour of an NSButton as part of the Popover example.

Below is the crux of the example (modified slightly for this post, untested):

NSButton *button = ...;
NSMutableAttributedString *attrTitle =
    [[NSMutableAttributedString alloc] initWithString:@"Make Me Red"];
NSUInteger len = [attrTitle length];
NSRange range = NSMakeRange(0, len);
[attrTitle addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:range];
[attrTitle fixAttributesInRange:range];
[button setAttributedTitle:attrTitle];

Note that the call to fixAttributesInRange: seems to be important (an AppKit extension), but I can't find documentation as to why that is the case. The only concern I have with using attributed strings in an NSButton is if an image is also defined for the button (such as an icon), the attributed string will occupy a large rectangle and push the image to the edge of the button. Something to bear in mind.

Otherwise it seems the best way is to make your own drawRect: override instead, which has many other pitfalls that are outside the scope of this question.

Flutist answered 8/11, 2013 at 10:55 Comment(0)
B
5

I've created a NSButton subclass called FlatButton that makes it super-easy to change the text color in the Attributes Inspector of Interface Builder like you are asking for. It should provide a simple and extensive solution to your problem.

It also exposes other relevant styling attributes such as color and shape.

You'll find it here: https://github.com/OskarGroth/FlatButton

FlatButton for macOS

Burchette answered 22/4, 2017 at 10:26 Comment(0)
Z
3

Add a category on the NSButton and simply set the color to what you want, and preseve the existing attributes, since the title can be centered, left aligned etc


@implementation NSButton (NSButton_IDDAppKit)

- (NSColor*)titleTextColor {

    return [NSColor redColor];

}

- (void)setTitleTextColor:(NSColor*)aColor {

    NSMutableAttributedString*  attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedTitle];
    NSString*  title = self.title;
    NSRange  range = NSMakeRange(0.0, self.title.length);

    [attributedString addAttribute:NSForegroundColorAttributeName value:aColor range:range];
    [self setAttributedTitle:attributedString];
    [attributedString release];

}

@end
Zingg answered 8/2, 2016 at 15:56 Comment(0)
E
3

A really simple, reusable solution without subclassing NSButton:

[self setButton:self.myButton fontColor:[NSColor whiteColor]] ;

-(void) setButton:(NSButton *)button fontColor:(NSColor *)color {
    NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[button attributedTitle]];
    [colorTitle addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, button.attributedTitle.length)];
    [button setAttributedTitle:colorTitle];
}
Elmaelmajian answered 27/3, 2017 at 11:43 Comment(0)
U
3

When your target is macOS 10.14 or newer, you can use the new contentTintColor property of the NSButton control to set the text color.

button.contentTintColor = NSColor.systemGreenColor;
Uranyl answered 14/12, 2018 at 17:53 Comment(1)
contentTintColorTamathatamaulipas
V
3

If deployment Target > 10.14,you can use contentTintColor set color.

/** Applies a tint color to template image and text content, in combination with other theme-appropriate effects. Only applicable to borderless buttons. A nil value indicates the standard set of effects without color modification. The default value is nil. Non-template images and attributed string values are not affected by the contentTintColor. */
@available(macOS 10.14, *)
@NSCopying open var contentTintColor: NSColor?

sample code:

var confirmBtn = NSButton()
confirmBtn.title = "color"
confirmBtn.contentTintColor = NSColor.red
Viperish answered 7/1, 2021 at 15:55 Comment(0)
Q
2

Swift 5

You can use this extension:

extension NSButton {
    @IBInspectable var titleColor: NSColor? {
        get {
            return NSColor.white
        }
        set {
            let pstyle = NSMutableParagraphStyle()
            pstyle.alignment = .center
            self.attributedTitle = NSAttributedString(
                string: self.title,
                attributes: [ NSAttributedString.Key.foregroundColor :newValue, NSAttributedString.Key.paragraphStyle: pstyle]
            )
        }
    }
}

Now you can set title color in storyboard easily. Cheers!

Quechuan answered 3/8, 2020 at 6:42 Comment(0)
C
1
NSColor color = NSColor.White;  
NSMutableAttributedString colorTitle = new NSMutableAttributedString (cb.Cell.Title);                
NSRange titleRange = new NSRange (0, (nint)cb.Cell.Title.Length);
colorTitle.AddAttribute (NSStringAttributeKey.ForegroundColor, color, titleRange);      
cb.Cell.AttributedTitle = colorTitle;  
Chartulary answered 9/3, 2016 at 18:1 Comment(2)
Could you add some text to explain your solution?Jolynjolynn
This is an answer for Xamarin.Mac. It helped me. One thing I'd recommend is basing the attributed string on button.AttributedTitle instead of button.Cell.Title so to preserve any other (implicit) attributes the title had.Laurettelauri
S
1

Using the info above, I wrote a NSButton extension that sets the foreground color, along with the system font and text alignment.

This is for Cocoa on Swift 4.x, but could be easily adjusted for iOS.

import Cocoa

extension NSButton {
    func setAttributes(foreground: NSColor? = nil, fontSize: CGFloat = -1.0, alignment: NSTextAlignment? = nil) {

        var attributes: [NSAttributedStringKey: Any] = [:]

        if let foreground = foreground {
            attributes[NSAttributedStringKey.foregroundColor] = foreground
        }

        if fontSize != -1 {
            attributes[NSAttributedStringKey.font] = NSFont.systemFont(ofSize: fontSize)
        }

        if let alignment = alignment {
            let paragraph = NSMutableParagraphStyle()
            paragraph.alignment = alignment
            attributes[NSAttributedStringKey.paragraphStyle] = paragraph
        }

        let attributed = NSAttributedString(string: self.title, attributes: attributes)
        self.attributedTitle = attributed
    }
}
Snyder answered 10/5, 2018 at 19:41 Comment(0)
B
0

Swift 4.2 version of David Boyd's solution

extension NSButton {
func setAttributes(foreground: NSColor? = nil, fontSize: CGFloat = -1.0, alignment: NSTextAlignment? = nil) {

    var attributes: [NSAttributedString.Key: Any] = [:]

    if let foreground = foreground {
        attributes[NSAttributedString.Key.foregroundColor] = foreground
    }

    if fontSize != -1 {
        attributes[NSAttributedString.Key.font] = NSFont.systemFont(ofSize: fontSize)
    }

    if let alignment = alignment {
        let paragraph = NSMutableParagraphStyle()
        paragraph.alignment = alignment
        attributes[NSAttributedString.Key.paragraphStyle] = paragraph
    }

    let attributed = NSAttributedString(string: self.title, attributes: attributes)
    self.attributedTitle = attributed
}

}

Boatwright answered 23/1, 2019 at 10:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.