34

I am trying to add a custom view in the center of a navigation bar and I am using the following code to test it:

UIView * testView = [[UIView alloc] init];
[testView setBackgroundColor:[UIColor blackColor]];
testView.frame = CGRectMake(0, 0, 100, 35);
[self.navigationController.navigationItem.titleView addSubview:testView];

I am setting this up in the viewDidLoad method of my view controller but when i run my program nothing seems to change in my navigation bar.

Could you help me with this?

Krunal
  • 77,632
  • 48
  • 245
  • 261
Julian Osorio
  • 1,116
  • 1
  • 12
  • 30
  • Check out this post... [custon uinavigationbars supportable for iOS4 and iOS5][1] [1]: http://stackoverflow.com/questions/7657465/uinavigationbars-drawrect-is-not-called-in-ios-5-0 Hope it helps.. :) – Shrey Dec 08 '11 at 15:16

8 Answers8

68

This works. Give frame at the time of initialisation

UIView *iv = [[UIView alloc] initWithFrame:CGRectMake(0,0,32,32)];
[iv setBackgroundColor:[UIColor whiteColor]];
self.navigationItem.titleView = iv;
aturan23
  • 4,798
  • 4
  • 28
  • 52
virata
  • 1,882
  • 15
  • 22
  • 3
    Yes that was exactly it! Thanks a lot! can i ask you why i can't access to the navigation item using: "self.navigationController.navigationItem.titleView" is it wrong to access the navigation item from the navigation controller. Thanks a lot @virata – Julian Osorio Dec 08 '11 at 15:28
  • 3
    @JulianOsorio It's not the problem about `self.navigationItem.titleView` and `self.navigationController.navigationItem.titleView`, it's the different between `addSubview` and `setTitleView`. :) – Kjuly Dec 08 '11 at 15:33
  • u r welcome Julian,navigationItem is your class's own property. Don't try to access it through navigationController's property. – virata Dec 08 '11 at 15:36
  • Excellent I get it now! Thanks to you two. – Julian Osorio Dec 08 '11 at 15:45
  • 2
    Weird, it doesn't work on iOS 7.. I added a searchBar.. and I get complaints about autolayout stuffs.. – Van Du Tran Oct 05 '13 at 15:20
34

If you want to just customize the title for one view controller you can use

UILabel *lblTitle = [[UILabel alloc] init];
lblTitle.text = @"Diga-nos o motivo";
lblTitle.backgroundColor = [UIColor clearColor];
lblTitle.textColor = [UIColor colorWithRed:77.0/255.0 green:77.0/255.0 blue:77.0/255.0 alpha:1.0];
lblTitle.shadowColor = [UIColor whiteColor];
lblTitle.shadowOffset = CGSizeMake(0, 1);
lblTitle.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:18.0];
[lblTitle sizeToFit];

self.navigationItem.titleView = lblTitle;

or if you want to customize for all view controllers use

[[UINavigationBar appearance] setTitleTextAttributes:
    [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0], 
        UITextAttributeTextColor, 
        [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8], 
        UITextAttributeTextShadowColor, 
        [NSValue valueWithUIOffset:UIOffsetMake(0, -1)], 
        UITextAttributeTextShadowOffset, 
        [UIFont fontWithName:@"Arial-Bold" size:10.0], 
        UITextAttributeFont, 
        nil]];
Raphael Oliveira
  • 7,751
  • 5
  • 47
  • 55
27

Replace

[self.navigationController.navigationItem.titleView addSubview:testView];

to

self.navigationItem.titleView = testView;

Edit:

Note: You cannot add subviews to titleView cause it's default value is nil, you need to set a new view as the titleView.

Kjuly
  • 34,476
  • 22
  • 104
  • 118
  • But you can add a subview to `self.navigationController.navigationBar`. – Kyle Clegg Jun 17 '14 at 19:54
  • @KyleClegg um.. I don't like to add subviews on navigation bar, except button items. ;) – Kjuly Jun 18 '14 at 01:17
  • @Kjuly agreed, I was just trying to get a `UIPageControl` in the nav bar similar to the Twitter app and that's how I was able to do it easily. Depending on how you want to customize the titleview it can be useful. – Kyle Clegg Jun 18 '14 at 04:34
  • But adding titleview is not covering the full navigation bar. Looks like comes with its own default insets :-( – kidsid49 Apr 18 '15 at 14:40
2

Swift 3/4

You may set i.e. UILabel as a titleView. Call it in viewDidLoad():

private func setNavigationTitle(_ title: String) {
    navigationItem.title = nil // clear the default title
    let titleLabel = UILabel() // you don't need to specify a frame, it will be centred in the navbar
    titleLabel.font = ...
    titleLabel.textColor = ...
    titleLabel.text = title
    titleLabel.backgroundColor = .clear
    navigationItem.titleView = titleLabel
    navigationTitleView = titleLabel // you may create a property if you want to manipulate the title view later
}

Note navigationItem.title = nil, otherwise title may override titleView.

nikans
  • 2,468
  • 1
  • 28
  • 35
1
CustomLabel *titleLabel = [CustomLabel initWithLabelFrame:labelFrame textFont:[UIFont fontWithName:@"Helvetica" size:[UIFont systemFontSize]] textColor:[UIColor blackColor] labelText:@"Add as" textAlignment:NSTextAlignmentCenter labelOnView:reference.view labelTag:62];

[self.navigationItem setTitleView:titleLabel]; // titleLabel set in navigationItem
Sandy Patel
  • 768
  • 7
  • 19
  • Hello and welcome to Stack Overflow! Please edit your answer to put the code inside a code block to make it more readable. This can be done by putting four spaces at the start of each line, or marking the code and pressing the `{}` button. – Anders Sep 13 '15 at 06:47
1
#import <UIKit/UIKit.h> 
@interface MasterViewController : UITableViewController
@end


#import "MasterViewController.h"
@interface MasterViewController ()
@end

@implementation MasterViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.titleView = [self titleView];
}

- (UIView *)titleView {
    CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
    CGFloat width = 0.95 * self.view.frame.size.width;
    UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, navBarHeight)];

    UIImage *logo = [UIImage imageNamed:@"logo.png"];
    UIButton *logoButton = [UIButton buttonWithType:UIButtonTypeCustom];
    CGFloat logoY = floorf((navBarHeight - logo.size.height) / 2.0f);
    [logoButton setFrame:CGRectMake(0, logoY, logo.size.width, logo.size.height)];
    [logoButton setImage:logo forState:UIControlStateNormal];

    UIImage *bubble = [UIImage imageNamed:@"notification-bubble-empty.png"];
    UIImageView *bubbleView = [[UIImageView alloc] initWithImage:bubble];

    const CGFloat Padding = 5.0f;
    CGFloat bubbleX = 
        logoButton.frame.size.width + 
        logoButton.frame.origin.x + 
        Padding;
    CGFloat bubbleY = floorf((navBarHeight - bubble.size.height) / 2.0f);
    CGRect bubbleRect = bubbleView.frame;
    bubbleRect.origin.x = bubbleX;
    bubbleRect.origin.y = bubbleY;
    bubbleView.frame = bubbleRect;

    [containerView addSubview:logoButton];
    [containerView addSubview:bubbleView];

    return containerView;
}

@end
Durul Dalkanat
  • 7,266
  • 4
  • 35
  • 36
0

You'll want to use storyboard to do this to support iPhone 6 and newer (larger) devices.

Create a container view for your custom navigation item title/subtitle etc, and drag it into the visual editor (not into the view hierarchy).

Ray W
  • 679
  • 4
  • 12
0

Swift 3

let myImageView = UIImageView(image: <...set your image...>)

override fun viewDidLoad(){
   super.viewDidLoad()
   self.navigationItem.titleView = myImageView  //
}

One more alternate solution is

override fun viewWillAppear(_ animated: Bool) {
   super. viewWillAppear(animated)
   self.navigationItem.titleView = myImageView
}

I recommend to use, viewDidLoad to setup your titleView

Krunal
  • 77,632
  • 48
  • 245
  • 261