I want to set the common Bar Button Item on the right of the Navigation Bar, it should be display on all screens managed by Navigation Controller and it calls the same action.
Just for example, in Master Detail Application template, there is "addButton" on the right of the Navigation Bar, I want to display it on DetailViewController as well (it won't be work because action is missing though).
I have created a subclass of UINavigationController, in which I can change something like Navigation Bar color, but I can't set Bar Button Items. I can set Bar Button Items in each screen's ViewController so that I have to duplicate action for each screen.
Also I've tried to create a subclass of UINavigationBar, but I don't know if I can add Bar Button Item on it.
How to set common Bar Button Item on Navigation Bar?
Thanks in advance.
Another easy way to do instead of creating an extension
implement UINavigationControllerDelegate in root view controller
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
let backBarButton = UIBarButtonItem.init(title: "HINIBO", style: .Plain, target: self, action: Selector("menuButtonAction:"))
viewController.navigationItem.rightBarButtonItem = backBarButton
}
You can use category to approach it. Let's say UIViewController+NavigationBar category
1.Create a category
2.Add a method, -(void)setNavigationBarItem method (in this case) in .h file.
3.implement the method in .m file to deal with the set Bar Button Items stuff.
- (void)setNavigationBarItem
{
UIBarButtonItem *searchItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:#selector(something)];
self.navigationItem.rightBarButtonItem = searchItem;
}
4.In which viewController you want the NavigationBarItem, import the category header and call [self setNavigationBarItem] method.
Related
How can one push a new navigation controller from an existing navigation controller, as is done for Facebook's instant articles pictured below?
In this case, would you have to create a view controller schema with a master navigation controller with a translucent navigation bar that wraps both the Facebook tab bar / navigation controller and the instant article navigation controller?
Facebook instant article
Edit: Added Snapchat example
Are you thinking of the different UINavigationBar rather than the UINavigationController? I think you can already change the bar appearance for a different UIViewController... if its being a problem then you can make a class for the UINavigationController and add functionality in there to change appearance of the bar for what ever the UIViewController is being viewed.
The delegate methods of the UINavigationController give you methods like
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool)
Inside that you can put a check like
if viewController.isKind(of: SomeViewController.self) {
//make this specific change for it
} else if viewController.isKind(of: SomeOtherViewController.self) {
//make this specific change for this other viewController
} else {
//make this for all other
}
In my app's main view, I have a button that segues to a subclassed UINavigationController holding a UITableViewController to change settings.
To get back to the app's main view, I have this in the UINavigationController subclass:
navigationBar.setItems([UINavigationItem(title: "Back"),
UINavigationItem(title: "Settings")],
animated: false)
When I tab the Back button, the app segues back to the same view - but the navigation bar now only have the Settings item.
When I click the Back button, I want to dismiss the UINavigationController subclass and come back to my main view.
So how do I get a touchUpInside event on the UINavigationItem or is there some other way I can do this?
So it turns out there's a very easy way of doing this:
adding a UIBarButtonItem in the storyboard
subclass the UITableViewController
control-drag from the UIBarButtonItem to the UITableViewController subclass to create an action
dismiss the UITableViewController in the action
Is it possible to set-up a navigation structure using the Interface Builder, without using the standard Apple navigation bar? I want to apply the actions which open a new View Controller to my own custom buttons.
Is this is not possible, do you guys have a good place where I can start learning to do this without using the interface builder?
you have to embed navigation controller with your root view controller. For that select your view controller in your storyboard click on editor->embed in->navigationController.
In viewDidload write
self.navigationController?.navigationBar.hidden = true
have one label of size of navigation bar at the top add a button on it and write following code in it's action method
#IBAction func goToNextController(sender: AnyObject)
{
let second = self.storyboard?.instantiateViewControllerWithIdentifier("second") as SecondViewController
self.navigationController?.pushViewController(second, animated: true)
}
here secondViewController is the one which we are pushing
similarly have a label and button at the top in secondViewcontroller and write following cod e in your button's action method
![#IBAction func previousButtonTapped(sender: AnyObject)
{
self.navigationController?.popViewControllerAnimated(true)
}][2]
In IB you can change the class for the navigation bar to your own class.
If you don't use IB you can use [[UINavigationController alloc] initWithNavigationBarClass:[MyNavBar class] toolbarClass:nil]
I Have UINavigationController in my app, I want to have a right UIBarButtonItem to be shown in all navigation bar that appear in my application. this button will load menu, so I don't want to add this button in every navigation bar manually, also as the function is loading menu, I don't want to copy/past action for this button.
is there any way to handle this in ViewController.h and .m ?
so the button act as a universal bar button item?
What you can do is subclass the navigation controller. Here is an example
#interface NavigationController : UINavigationController
#end
#interface NavigationController () <UINavigationBarDelegate>
#end
#implementation NavigationController
- (void)viewDidLoad
{
[super viewDidLoad];
for (UIViewController* viewController in self.viewControllers){
// You need to do this because the push is not called if you created this controller as part of the storyboard
[self addButton:viewController.navigationItem];
}
}
-(void) pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
[self addButton:viewController.navigationItem];
[super pushViewController:viewController animated:animated];
}
-(void) addButton:(UINavigationItem *)item{
if (item.rightBarButtonItem == nil){
item.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(action:)];
}
}
-(void) action:(UIBarButtonItem*) button{
}
#end
This cannot be done unless you use a custom view to look like NavigationBar.
By default, NavigationController clears all bar button items when a ViewController is pushed or popped. So for every ViewController, you need to create UIBarButtonItem every time in function
- (void)viewWillAppear:(BOOL)animated
or use can subclass UINavigationController and do as #rp90 answer.
You can add a button that appears in your UINavigationController by adding it in the UINavigationController's delegate - in this example, a singleton helper class.
Swift 3:
class NavHelper: UINavigationControllerDelegate {
static let shared = NavHelper()
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
let barButtonItem = UIBarButtonItem(image: <yourButtonImage>, style: .plain, target: NavHelper.shared, action: #selector(NavDelegate.handleButton(_:)))
viewController.navigationItem.rightBarButtonItem = barButtonItem
}
func handleButton(_ sender: UIBarButtomItem) {
<yourCode>
}
}
Another option is to make your own navigation bar view as a part of the UIViewController. You can turn off Apple's and build your own. We did this to provide our own controls easier. The only thing you lose is the easy translucency under iOS 7. A lot of apps do this for the same reason we did.
You can create a new class that inherits from UIViewController and in the viewDidLoad method, create a UIBarButtonItem and add it to the navigationItem as a left/right bar item. Let's say this class is called CustomBarViewController:
UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithTitle:#"hi" style:UIBarButtonItemStylePlain target:self action:#selector(doSomething:)];
[self.navigationItem setRightBarButtonItem:barItem];
In your existing view controllers, instead of having them inherit from UIViewController in the .h file, you can have them use CustomBarViewController instead:
#interface MyExistingViewController : CustomBarViewController
You can then put actions into the doSomething: method, or have it pass notifications to your existing view controllers.
You can add the button into a ContainerView. Thus it will be on at all times.
Food for thought....
I have a tab bar controller with 4 views controller, and have this tab bar controller in a navigation controller.
I want to display a UIBarButtonItem for just one specific view controller of the tab bar controller.
I tried to use the following
if (tabBarController.selectedViewController == customTourViewController)
{
[tabBarController.navigationItem setRightBarButtonItem:done];
}
But the button doesn't show up.
If I put every view controller in a navigation controller, then the button shows up for only that view, but I end up having 2 navigation bars.
Is there any way I can implement the first solution?
Thanks.
In my individual view controllers for the individual tabs, I have the following in the one that needs the button:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonSystemItemDone target:nil action:nil];
self.tabBarController.navigationItem.rightBarButtonItem = rightButton;
}
And in the view controllers that don't need the button, I have:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.tabBarController.navigationItem.rightBarButtonItem = nil;
}
So, if it's not working for you, I'm not sure if it's your reference to tabBarController without the self designation (if I omit the self I get a compiler error). And where is this code because if it's in your tabBarController subclass, then you want self.navigationItem.rightBarButtonItem, right? Do you have your own ivar defined for that variable name? Or are you sure that done is defined properly (i.e. not nil)? Or are you sure this code is being called at all (perhaps set a breakpoint or insert a NSLog and make sure this code is being reached)?
Alternatively you can implement viewWillDisappear in the same view where you need the button.
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.tabBarController.navigationItem.rightBarButtonItem = nil;
}
The accepted answer above is exactly what I needed, just wanted to convert it to Swift for those in the future.
I've added the code below to the view controller that required the bar button (I've created an add button for this example):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: nil)
}
In the view controllers that don't require this bar button, simply add the code below
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.rightBarButtonItem = nil
}
You use viewWillAppear vice viewDidAppear because you want the bar button to appear every time the user goes to the designated view controller.
Simply put, viewDidAppear is called once at runtime, viewWillAppear will be called every time the view controller is visited.