I want to override to my own navigation controller with its own back button, title etc. But after i pushed the view controller, by default shows the navigation bar of the last view in the stack which was inherited in previous class.
Lets assume this is my first class which inherits NavBarViewController in header file as;
//ListingDetailViewController.h
#interface ListingDetailViewController : NavBarViewController
and, inside ListingDetailViewController, i pushed view by:
//ListingDetailViewController.m
ChatListViewController *chatList= [[ChatListViewController alloc]init];
[self.navigationController pushViewController:chatList animated:YES];
So this will still bring in the navigation controller same as in ListingDetailViewController, even though i tried to override the back button, title again in ChatListViewController's viewdidLoad and viewWillAppear. This is ChatListViewController's header:
//ChatListViewController.h
#interface ChatListViewController : IPChatListViewController
How can i achieve this? Any help is much appreciated. Thank you.
I use a BaseViewController class for this purpose. Paste this code in your base controller:
if (self.navigationController.viewControllers)
{
if (self.navigationController.viewControllers.count > 1)
{
[self createBackButton];
}
else
{
//[self createSideBarButton];
}
}
else
{
//[self createSideBarButton];
}
Include this method in your base class:
- (UIBarButtonItem *)createBackButton
{
UIBarButtonItem *negativeSeperator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSeperator.width = 0;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"navigation_back_button.png"] style:UIBarButtonItemStylePlain target:self.navigationController action:#selector(popViewControllerAnimated:)];
[item setTintColor:[UIColor whiteColor]];
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:negativeSeperator,item, nil];
return item;
}
If you make sure you subclass your View Controllers (not navigation controller) from this base VC it will automatically replace back buttons.
I found the solution by overriding the button in viewDidAppear, because until viewDidLoad it will re-use the inherited navigation bar. So,
-(void)viewDidAppear:(BOOL)animated {
[self overwriteBackButton];
}
Then:
- (void)overwriteBackButton {
UIImage *backNormal = [UIImage imageNamed:#"backButton"];
_navBarLeftButton = [OpenSansButton buttonWithType:UIButtonTypeCustom];
_navBarLeftButton.frame = CGRectMake(10, 10, 35, 35);
[_navBarLeftButton setImage:backNormal forState:UIControlStateNormal];
[_navBarLeftButton addTarget:self action:#selector(backToList) forControlEvents:UIControlEventTouchUpInside];
[self.navigationController.navigationBar addSubview:_navBarLeftButton];
}
And it is triggered to:
-(void)backToList
{
[self.navigationController popViewControllerAnimated:YES];
}
Related
I want to change the title of post buttons in SLComposeServiceViewController.
I managed to get the UIButton:
NSArray* subviews =[self.navigationController.navigationBar subviews];
UIButton* postButton =[subviews lastObject];
and i tried to set title like this:
[postButton setTitle:#"Save" forState:UIControlStateNormal];
but the title not changed.
Can anyone help me with this?
I saw Evernote's share extension on my iPad and it looks like this:
UPDATE
My Solution:
I found solution for my question,I removed the original navigation bar and create custom nav bar.
I have two nav bar:
1. with "cancel"\"save" buttons
2. with "back" button
and I change them when navigate to other viewcontroller
(in my case I needed to upload file and user need select location from list)
NOTE: if you not implement configurationItems you need only the first nav bar. (just call to set custom nav bar from viewDidAppear
So my code is here:
#property (strong, nonatomic) UINavigationBar *customNavBar;
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.customNavBar = [[UINavigationBar alloc] initWithFrame:self.navigationController.navigationBar.bounds];
[self.navigationController.navigationBar removeFromSuperview];
[self.navigationController.view addSubview:self.customNavBar];
[self setCancelSaveNavigationItem];
}
setCancelSaveNavigationItem--> called from viewDidAppear of shareViewController
-(void)setCancelSaveNavigationItem
{
UINavigationItem *newItem = [[UINavigationItem alloc] init];
UIBarButtonItem *cancelBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Cancel",nil) style:UIBarButtonItemStylePlain target:self action:#selector(cancelButtonTapped:)];
UIBarButtonItem *saveBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Done",nil) style:UIBarButtonItemStyleDone target:self action:#selector(saveButtonTapped:)];
newItem.leftBarButtonItem = cancelBarButtonItem;
newItem.rightBarButtonItem = saveBarButtonItem;
[self.customNavBar setItems:#[newItem]];
[self.navigationItem setBackBarButtonItem:cancelBarButtonItem];
[self.navigationItem setRightBarButtonItem:saveBarButtonItem];
if(self.item.value == nil){
saveBarButtonItem.enabled = NO;
}
}
setBackNavigationItem--> called in configurationItems -->in self.item.tapHandler function
-(void)setBackNavigationItem
{
UINavigationItem *newItem = [[UINavigationItem alloc] init];
UIBarButtonItem *selectBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Select",nil) style:UIBarButtonItemStylePlain target:self action:#selector(selectButtonTapped:)];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:[NSString stringWithFormat:#"❮ %#", NSLocalizedString(#"Back",nil)] style:UIBarButtonItemStylePlain target:self action:#selector(backButtonTapped:)];
newItem.leftBarButtonItem = backBarButtonItem;
newItem.rightBarButtonItem = selectBarButtonItem;
[self.customNavBar setItems:#[newItem]];
[self.navigationItem setBackBarButtonItem:backBarButtonItem];
[self.navigationItem setRightBarButtonItem:selectBarButtonItem];
}
Handle buttons tapped:
- (void)backButtonTapped:(id)sender {
if([self.navigationController.viewControllers count] ==2){
[self setCancelSaveNavigationItem];
}
[self.navigationController popViewControllerAnimated:YES];
}
- (void)cancelButtonTapped:(id)sender {
[self cancel];
}
- (void)selectButtonTapped:(id)sender {
...
[self setCancelSaveNavigationItem];
[self popConfigurationViewController];
}
- (void)saveButtonTapped:(id)sender {
...
[self cancel];
}
And it's work for me!!!
The result:
Simply in viewDidAppear
self.navigationController?.navigationBar.topItem?.rightBarButtonItem?.title = "Save"
Your code:
NSArray* subviews =[self.navigationController.navigationBar subviews];
UIButton* postButton =[subviews lastObject];
...is a really bad idea. It only works because the post button is in subviews and is the last item in the array. But the content of subviews is undocumented and might change at any time. Also, since there's no public API for this button, it's entirely possible that there's framework code to prevent or override changes to the button text-- so even if we assume you have the right UI element, you still might not be able to change it.
Evernote's UI is almost certainly a full custom design that only resembles SLComposeServiceViewController. Share extensions are not required to use SLComposeServiceViewController, that's just there for convenience. If it doesn't meet your needs, design your own.
Update: out of curiosity I unzipped the Evernote IPA and had a look at EvernoteShare.appex with nm. There's no reference to SLComposeServiceViewController, which confirms that Evernote is not using that class in their extension.
I have a tab bar controller as my root view with 5 navigation controllers (one for each tab). The navigation bar in each tab will have a button that has the same functionality across all tabs. Is there an easier way to add this button (and respond to selection) than copy/pasting it into each navigation controller?
EDIT:
In my custom navigation controller's child view controller, I have:
- (void)viewDidLoad
{
[super viewDidLoad];
...
CustomNavigationController *navController = [self.storyboard instantiateViewControllerWithIdentifier:#"HomeNavigationController"];
[navController addNotificationsButton:YES searchButton:NO];
}
and in the custom navigation controller I have:
-(void)addNotificationsButton:(BOOL)notifications searchButton:(BOOL)search { //Choose which bar button items to add
NSMutableArray *barItems = [[NSMutableArray alloc]init];
if (notifications) {
//Create button and add to array
UIImage *notificationsImage = [UIImage imageNamed:#"first"];
UIBarButtonItem *notificationsButton = [[UIBarButtonItem alloc]initWithImage:notificationsImage landscapeImagePhone:notificationsImage style:UIBarButtonItemStylePlain target:self action:#selector(notificationsTap:)];
[barItems addObject:notificationsButton];
}
if (search) {
//Create button and add to array
UIBarButtonItem *searchButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:#selector(searchTap:)];
[barItems addObject:searchButton];
}
[self.navigationItem setRightBarButtonItems:barItems];
}
But I just get an empty navigation bar when the child view controller loads. Any ideas?
EDIT 2:
I just had to add an argument for the view controller who's navigation bar I wanted to add buttons to. Here is the final implementation...
for CustomViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
...
CustomNavigationController *navController = [self.storyboard instantiateViewControllerWithIdentifier:#"HomeNavigationController"];
[navController addNotificationsButton:YES searchButton:NO forViewController:self];
}
For CustomNavigationController.m
-(void)addNotificationsButton:(BOOL)notifications searchButton:(BOOL)search forViewController:(UIViewController*)vc { //Choose which bar button items to add
NSMutableArray *barItems = [[NSMutableArray alloc]init];
if (notifications) {
//Create button and add to array
UIImage *notificationsImage = [UIImage imageNamed:#"first"];
UIBarButtonItem *notificationsButton = [[UIBarButtonItem alloc]initWithImage:notificationsImage landscapeImagePhone:notificationsImage style:UIBarButtonItemStylePlain target:self action:#selector(notificationsTap:)];
[barItems addObject:notificationsButton];
}
if (search) {
//Create button and add to array
UIBarButtonItem *searchButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:#selector(searchTap:)];
[barItems addObject:searchButton];
}
vc.navigationItem.rightBarButtonItems = barItems;
}
You need to create a subclass of UINavigationController,
configure it as you want (so with your button),
and set that as class of your 5 Navigation Controller.
Obviously i can't write here all your apps, but the important is that you have a way.
If you are a developer at the first times, i encourage you to study about subclassing etc.
Subclass navigation bar and add button as part of subclass. Now you can use 5 instances of the subclass instead of the 5 base navigation bars and cut out the repeated work of adding the buttons.
I have a "LoginViewController" which presents a new Controller which is a subclass of UINavigationcontroller when clicking a button:
MPNavigationViewController *controller = [[MPNavigationViewController alloc] initWithRootViewController:[[MPQuestionFirstViewController alloc] init]];
[self presentViewController: controller animated:YES completion:nil];
"MPNavigationViewController" subclass UINavigationController and uses "REMenu" to have a sliding-from-top menu ("Link") and on viewDidLoad I try to add a right button to open it:
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *toggleMenuButton = [[UIBarButtonItem alloc] initWithTitle:#"Show" style:UIBarButtonItemStylePlain target:self action:#selector(toggleMenu:)];
self.navigationItem.rightBarButtonItem = toggleMenuButton;
[self initMenu];
}
It doesn't show any button on the navigation bar. Why could it be?
If I try to add the button from one of the "viewControllers" that will handle sections on the menu. It shows the button, but it doesn't paint it at all.
Thanks.
You are using subclass of UINavigationcontroller which is not actually view controller.
There is only one solution, You need to create your custom button and add it to UINavigationbar as a subview..
Use this hope it will help.
UIBarButtonItem *doneButton =[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(goToDoneButtonAction)];
self.navigationItem.rightBarButtonItem = doneButton;
I want to navigate to the particular page in my application and i also dont want to create any custom back button for that.If I can override the method of the navigation bar back button so I can call the poptorootviewcontroller.so i can go to specific page. Anyone knows what is the method that is called by the navigation bar button and if we can use it?
You can try this.. Write your logic in this native method.
-(void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:YES];
// Your Code
}
You will have to provide the name and the implementation for the button method As there is no standard method ..
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonPressed)] autorelease];
implementation ..
-(void) backButtonPressed {
NSLog(#"Back button presses");
}
Try to use the below code:
NSArray * viewController = self.navigationController.viewControllers;
if([viewController count] > 3)
{
UIViewController * vc = [viewController objectAtIndex:0];
[self.navigationController popToViewController:vc animated:YES];
}
I dropped in a UINavigationBar in UIInterfaceBuilder. I present this view modally and just want a UIBackBarButton to return to my last view. I have an outlet and property to this UINavigationBar declared. I thought in my viewDidLoad method, I could create a UIBackButton like this:
UIBarButtonItem *backButton =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonItemStyleBordered
target:self
action:#selector(goBack)];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
But I do not see my UIBackBarButtonItem on the UINavigationBar. I think I am doing something wrong here since I don't think my UINavigationBar knows I'm trying to add this UIBackBarButtonItem to it in this way. Would I have to do create an NSArray, put the button in it, and setItems for the NavigationBar instead?
I'm confused on how the navigationItem property works vs the setItems of the UINavigationBar as well. Any help would be appreciated. Thanks!
You are trying to set the Back Button Item in a modal view which doesn't add a backBarButtonItem. This what causes the Button (or any sort of back button for that matter) not to show. The backBarButtonItem is mainly for use with Pushed View Controllers which have a Back Button added from the parent (next item below) when you push a new view controller (top item). The Apple UINavigationItem Documentation says:
When this item is the back item of the navigation bar—when it is the next item below the top item—it may be represented as a back button on the navigation bar. Use this property to specify the back button. The target and action of the back bar button item you set should be nil. The default value is a bar button item displaying the navigation item’s title.
To get the Back Button on the left side like you wish, Try changing
self.navigationItem.backBarButtonItem = backButton;
to
self.navigationItem.leftBarButtonItem = backButton;
making a call such as this from a view controller
{
NextViewController* vcRootView = [[NextViewController alloc] initWithNibName:#"NextView" bundle:[NSBundle mainBundle]];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:vcRootView];
[vcRootView release];
[self.navigationController presentModalViewController:navController animated:YES];
[navController release];
}
will present NextViewController as a Modal view on the calling view and NextViewController will have a navigationController for it.
In The NextViewController implementation file all you need is this
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self
action:#selector(barButtonBackPressed:)];
self.navigationItem.leftBarButtonItem = backButton;
[backButton release];
}
-(void)barButtonBackPressed:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
to have the back button to dismiss the modalview. Hope it helps.
Use below code snippet :
//Add button to NavigationController
UIBarButtonItem *backButton =
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#“back”, #"")
style:UIBarButtonItemStylePlain
target:self
action:#selector(goBack)];
self.navigationItem.leftBarButtonItem = backButton;
//Perform action on back Button
- (void) goBack { // Go back task over-here
}
Different style types available are :
UIBarButtonItemStylePlain, UIBarButtonItemStyleBordered, UIBarButtonItemStyleDone
You may use this setters without creation new UIBarButtonItem:
[self.navigationItem.leftBarButtonItem setAction:#selector(doBackButton:)];
[self.navigationItem.leftBarButtonItem setTarget:self];