How to properly subclass UINavigationBar also using appearance

This is what I'm trying to achieve: NavigationBar NB: Also with a header for the controller.

Additional Information: -

  • This navigation bar will appear on approximately 10 view controllers.
  • It is not part of the navigation controller, as it is not required.
  • The button on the left is static (it will always be in the navigation bar).
  • The right button is not static and will not or will not be different on different viewing controllers.
  • The left button acts as a sliding menu (i.e. menu slides in the lower left).
  • I use the storyboard in the settings

Question What is the right way to achieve this?

Existing code I tried to implement this, but I can only get one or the other of the buttons without a title. To implement the background, I used the appearance API, as shown 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 the UINavigationBar to create the left button with the following: Subclass of the 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, in the storyboard, I add a NavigationBar to the VC in question and refer to the correct subclass. I also add an additional button element to the navigation bar in the storyboard for this controller and plug into the outlet. Then in VC, I try to update the header and right button below:

View a controller that subclasses 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]; 

As a result, the navigation bar appears with only the left button. Now I believe that this is due to the awakeFromNib code above alloc init of the new UINavigationItem, so I cannot control the header and add a button to it. How can I complete this? Whether this is the best approach or there are others, I do not see detailed guides on how to approach this.

+7
source share
1 answer

Your best option is to use a navigation controller, it acts as a controller that interrogates the display controller currently being displayed and updates the navigation panel.

Instead of subclassing the navigation bar, you must subclass the navigation controller. Then, whenever the displayed view controller is displayed, you can set the left button element by adding it to the navigation element of this controller. Each view controller can indicate any elements (rows) that it requires.

The easiest way to do this is to configure the navigation controller as your own delegate and implement navigationController:willShowViewController: Using this method, he can access the navigationItem passed view controller and set leftBarButtonItem . If necessary, you also have access to other methods of navigation and viewing controllers.

Each view controller will also in viewDidLoad set its self.navigationItem.rightBarButtonItem(s) to the appropriate buttons for the requirements of its view. For example, your addGameButton button.

That way, the look will work the way you know it, the title of the view controller will work automatically, and you have full control and the number if there are methods in your subclass of the navigation controller to execute your button and interaction settings.

+10
source

All Articles