30

I am using UIAppearance to apply fonts to UINavigationBar and UIBarButtonItem and I am having problems. I ran this code:

[[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil] 
setTitleTextAttributes:
@{NSFontAttributeName : [UIFont fontWithName:@"My_Font" size:17.0]} 
forState:UIControlStateNormal];

NSLog(@"%@", [[UIBarButtonItem appearanceWhenContainedIn:
[UIToolbar class], nil] titleTextAttributesForState:UIControlStateNormal]);

and the result of that log on iOS 7 is:

(null)

Where the result in iOS 6 is:

{
    NSFont = "<UICFFont: 0x1d897a80> font-family: \"My_Font\"; font-weight: normal; font-style: normal; font-size: 17px";
}

I can't find anything in the iOS 7 docs that would indicate that this shouldn't work, has anyone else had this problem?

Edit 1

I actually have gotten this to work with [UINavigationBar appearance] the problem was that I was setting the point size to 0 in order to have the font be set to the default navbar/barButtonItem size as described in the NSString UIKit Additions Reference but this apparently no longer works in iOS 7. Instead, setting the point size to 0 will return the system font.

I am still unable to set titleTextAttributes to

[UIBarButtonItem appearanceWhenContaintedIn:[UIToolbar class], nil]]

LOP_Luke
  • 3,150
  • 3
  • 22
  • 25
  • did you find a fix for that ? – iosMentalist Mar 24 '14 at 07:58
  • No, as of iOS 7.1 the problem still exists with `[UIBarButtonItem appearance]`. Neither changing the dictionary keys to the NS prefix or moving the calls to `-viewDidLoad` fixed the problem. (`[UINavigationBar appearance]` works as long as the font's point size is greater than 0.) – LOP_Luke Mar 24 '14 at 17:19

7 Answers7

49
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont 
    fontWithName:@"YOURFONT" size:14], NSFontAttributeName, 
    [UIColor whiteColor], NSForegroundColorAttributeName, nil];

[[UINavigationBar appearance] setTitleTextAttributes:attributes];

The key is to use NSFontAttributeName and so forth. I assume they are moving over to using the NS variety for 64-bit compatibility. The above code worked on my iOS7 device.

TMilligan
  • 3,520
  • 1
  • 18
  • 12
  • Ahh that makes sense, what about the UIBarButtonItem though. When I try to set `titleTextAttributes` to a `[UIBarButtonItem appearance]` it seems to just be ignored. Were you able to get the appearance proxy to work with UIBarButtonItem? Also thanks for the help. – LOP_Luke Sep 20 '13 at 14:26
  • 2
    What is the default font size of Back button of navigation bar in iOS7 – Bharat Sep 23 '13 at 07:59
  • This saved me a lot of time! Thanks! What is the name of the default font? I want to match the default font but with blue color to match the blue UI elements in iOS7. – Jackson Sep 28 '13 at 19:01
18

Following @Alex Zavatone's answer - it could be done nicely in just one line of code:

self.navBar.titleTextAttributes = @{
    NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Light" size:20.0], 
    NSForegroundColorAttributeName: [UIColor redColor]
};
Jeremy Wiebe
  • 3,894
  • 22
  • 31
Sergey Grischyov
  • 11,995
  • 20
  • 81
  • 120
11

This worked fine for iOS 7 when I moved it to a viewDidLoad method in my view controller.

[[UIBarButtonItem appearance] setTitleTextAttributes:attributes];

When I tried to do this in AppDelegate it didn't work, though[[UINavigationBar appearance] setTitleTextAttributes:setTitleTextAttributes:attributes]; worked fine in AppDelegate. Also it should go before you create and assign the bar button.

It also works from initWithCoder method if you create your bar button on Storyboard.

Update: If you change deployment target to 7.0 then Xcode will provide you with warnings saying that for example UITextAttributeTextColor is deprecated and you should use NSForegroundColorAttributeName or instead of UITextAttributeFont use NSFontAttributeName. After changing attribute constants you can call setTitleTextAttributes: from AppDelegate.

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
Dmitry Volkov
  • 500
  • 1
  • 3
  • 14
  • What is the default font of size Back button of navigation bar in iOS7 – Bharat Sep 23 '13 at 08:00
  • When I read this, I was like: "Naah, I don't want to add it to all my `viewDidLoads`", which are just two superclasses. After I added it to one of them, I ran the app, and it worked for both... But not in `-[AppDelegate applicationDidFinishLaunching:withOptions:]`... No idea. – Mazyod Mar 08 '14 at 04:13
  • Note that it is now: [[UIBarButtonItem appearance] setTitleTextAttributes: attributes forState:<#(UIControlState)#>]; – Reefwing Oct 22 '15 at 00:16
9

Here's what I do on iOS-7

UIColor *red = [UIColor colorWithRed:165.0f/255.0f green:1.0f/255.0f blue:0.0f/255.0f alpha:1.0];
UIFont *font = [UIFont fontWithName:@"HelveticaNeue-Light" size:24.0f];

NSMutableDictionary *navBarTextAttributes = [NSMutableDictionary dictionaryWithCapacity:1];
[navBarTextAttributes setObject:font forKey:NSFontAttributeName];
[navBarTextAttributes setObject:red forKey:NSForegroundColorAttributeName ];

self.navBar.titleTextAttributes = navBarTextAttributes;
Alex Zavatone
  • 4,106
  • 36
  • 54
8

Here it is in Swift:

let font = UIFont(name: "My_Font", size: 17.0)
UINavigationBar.appearance().titleTextAttributes = [
    NSForegroundColorAttributeName: UIColor.whiteColor(),
    NSFontAttributeName: font!
]

*Note that you have to unwrap the optional UIFont.

yndolok
  • 5,197
  • 2
  • 42
  • 46
5

For the UIBarButons use the appearance proxy:

 NSDictionary *normalAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [UIFont fontWithName:@"Helvetica Neue" size:fontSize], UITextAttributeFont,
                                      nil];
    [[UIBarButtonItem appearance] setTitleTextAttributes:normalAttributes                                                                                                   
                                                forState:UIControlStateNormal];

If you want to limit which UIBarButtonItems your style affects use appearanceWhenContainedIn: instead.

For the UINavigationBar, you can create a UILabel and set it to your navigationItem.titleView:

UIabel *title = [[UILabel alloc] initWithFrame:CGRectZero];
title.backgroundColor = [UIColor clearColor];
title.font = [*yourfont*];
title.textColor = [*your color*];
self.navigationItem.titleView = title;
Andy Obusek
  • 12,614
  • 4
  • 41
  • 62
Will Jenkins
  • 9,507
  • 1
  • 27
  • 46
  • The appearance proxy doesn't work either for me. Were you actually able to get the font to change doing this? Also I know the UILabel trick but is that the only way to change the font now in iOS 7? In iOS 6 I was able to change the font with `titleTextAttributes` – LOP_Luke Sep 19 '13 at 15:48
  • 1
    Yes, I got the appearance proxy working but it did take a bit of jiggerypokery. I had to use appearanceWhenContainedIn with 2 levels of containment - i.e. [[UIBarButtonItem appearanceWhenContainedIn:[MyNavigationBar class],[MyNavigationController class],nil] ... – Will Jenkins Sep 19 '13 at 15:53
  • Note - the order of containment is back to front (from what I was expecting at least)... it goes from inner to outer – Will Jenkins Sep 19 '13 at 15:54
  • Regarding the UILabel, not sure if it's the only way but it was already implemented for iOS 6 and still works for 7. – Will Jenkins Sep 19 '13 at 15:56
1

Here is how to globally change the nav bar title's text color in Swift 4:

UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue: UIColor.yellow]
Josh Adams
  • 39
  • 3