Reputation: 6823
This is what I am trying to achieve:
NB: Also with a title to the controller.
Some additional information:-
Question What is the correct way to achieve this?
Existing Code I have tried to implement this, but I can only get one or the other of the buttons, without a title working. To implement the background I used the appearance API as below:
didFinishLaunching...
// Custom Navigation Bar appearance setup
[[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:245.0/255.0 green:245.0/255.0 blue:245.0/255.0 alpha:1.0], UITextAttributeTextColor,
[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5],UITextAttributeTextShadowColor,
[NSValue valueWithUIOffset:UIOffsetMake(0, 1)],
UITextAttributeTextShadowOffset,nil]];
// Used to deal with the rotation of the nav bar when implemented outside of Navigation Controller
[[UINavigationBar appearance] setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight];
[[UINavigationBar appearance] setContentMode:UIViewContentModeScaleAspectFit];
// Set the background image
UIImage *imageBg = [[UIImage imageNamed: @"mainNavBar"] resizableImageWithCapInsets:UIEdgeInsetsMake(0,5,0,5)];
[[UINavigationBar appearance] setBackgroundImage:imageBg forBarMetrics:UIBarMetricsDefault];
// Used to push the title down slightly when in Landscape and NavBar outside of Navigation Controller
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:2 forBarMetrics:UIBarMetricsLandscapePhone];
I then subclassed UINavigationBar for the left button creation with the following: Subclass of UINavigationBar: awakeFromNib
UINavigationItem* ni = [[UINavigationItem alloc] init];
UIButton *leftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 38.0f, 29.0f)];
[leftButton setImage:[UIImage imageNamed:@"menuBarItem"] forState:UIControlStateNormal];
[leftButton addTarget:nil action:@selector(menuItemPressed:) forControlEvents:UIControlEventTouchUpInside];
[leftButton setContentMode:UIViewContentModeScaleAspectFit];
[leftButton setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin];
UIBarButtonItem *b =[[UIBarButtonItem alloc] initWithCustomView:leftButton];
ni.leftBarButtonItem = b;
self.items = @[ni];
Then within the storyboard I add a NavigationBar to the VC in question and link to the correct subclass. I also add an additional button item to the navigation bar in the storyboard for that controller and link to an outlet. Then within the VC I try to update the title and right button with the below:
View Controller that holds the subclassed Nav Bar: viewDidLoad
// Set VC Title for NavBar
self.title = NSLocalizedString(@"NavBarHomeTitle", @"Navigation Bar - Home page title");
// Setup the right navigation bar item
UIImage *addImage = [UIImage imageNamed:@"addGameButton"];
UIButton *addButton = [UIButton buttonWithType:UIButtonTypeCustom];
[addButton setFrame:CGRectMake(0, 0, addImage.size.width, addImage.size.height)];
[addButton setBackgroundImage:addImage forState:UIControlStateNormal];
[addButton addTarget:self action:@selector(addGameButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.rightBarButtonItem setCustomView:addButton];
The result is a navigation bar with only the left button. Now I believe this is due to the awakeFromNib code above alloc init a new UINavigationItem therefore I cannot control the title and add a button to it. How can I complete this? Is this the best approach or are there others I cannot see any in-depth tutorials on how to approach this.
Upvotes: 7
Views: 5954
Reputation: 119031
Your better option is to use a navigation controller, it acts as the controller that interrogates the view controller it's currently displaying and updates the navigation bar.
Rather than subclass the navigation bar, you should subclass the navigation controller. Then whenever the displayed view controller changes you can set the left button item by adding it to the navigation item of that view controller. Each view controller can specify whatever right bar button item(s) it requires.
The simplest way to do this is for the navigation controller to act as its own delegate and implement navigationController:willShowViewController:
. Using this method it can access the navigationItem
of the passed view controller and set the leftBarButtonItem
. You also have access to the other methods of the navigation and view controllers if required.
Each view controller would also, in viewDidLoad
, set its self.navigationItem.rightBarButtonItem(s)
to appropriate buttons for the requirements of its view. Such as your 'addGameButton' bar button.
Working this way, the appearance will work as you have it, the title of the view controller will work automatically and you have full control, and a number if methods in your navigation controller subclass, to perform your button and interaction customisations.
Upvotes: 10