My application fit inside a UINavigationController.
Simply I setted up a MyUIViewController as rootViewController of navigationController and than I set up a customTitleView for the navigationItem of myViewController inside viewDidLoad.
Now when I push a newViewController I expect to see the previous customTitleView (as described by Apple NavigationController reference) but it doesn't.
What's wrong?
A little part of code below and the Apple UINavigationController Reference
"If the new top-level view controller has a custom title view, the navigation bar displays that view in place of the default title view. To specify a custom title view, set the titleView property of the view controller’s navigation item."
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationItem setTitleView:customTitleView];
}
Maybe the "default title view" means "nothing"? I interpreted it as the previous titleView.
EDIT
I'm trying a work around but I have some other issues.
The work around is:
In every ViewController that I push inside the NavigationController I setup in viewDidLoad the titleView getting it from the rootViewController
UiView *originalContainer = [[[self.navigationController.viewControllers objectAtIndex:0] navigationItem] titleView]
I create a newTitleView and I put inside the originalContainer.subviews (UIButton) cause I need the Target action from it.
All works perfectly for the first pushed controller but if I push another viewController in the stack (the second one pushed) I loose every reference to the navigationController. Every instance variables are nil.
This values are getted inside the viewDidLoad
firstViewControllerPushed.navigationController = (UINavigationController*)0x6693da0
firstViewControllerPushed.parentViewController = (UINavigationController*)0x6693da0
secondViewControllerPushedFromFirstViewControllerPushed.navigationController = 0x0
secondViewControllerPushedFromFirstViewControllerPushed.parentViewController = 0x0
It seems that the secondViewControllerPushed lives nowhere!!
How it's possible?
I double checked that I correctly push the viewController instead of present it modally
Couse this issue I'm not able to make a right setup of the newTitleView for the secondViewControllerPushed.
This is a hack in a half but I feel it gives you a bit more control in the viewController you are working in. So below is a small method I have setup and then I just call it in viewDidLoad - [self setUpNavBar];
And using [UIButton buttonWithType:101] is perfectly fine as it passed Apple Validation.
- (void) setUpNavBar
{
[self.navigationController setNavigationBarHidden: NO animated:YES];
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
self.title = #"Settings";
UIButton* backButton = [UIButton buttonWithType:101]; // left-pointing shape
[backButton addTarget:self action:#selector(backAction) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backItem;
[backItem release];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Logout"
style:UIBarButtonItemStylePlain target:self
action:#selector(logoutAction)] autorelease];
}
Related
I know I can set custom back button from the view controller itself, something like:
- (void)setBackButton
{
UINavigationBar* navBar = self.navigationController.navigationBar;
UIButton* backButton = [navBar backButtonWith:[UIImage imageNamed:#"navigationBarBackButton.png"]
highlight:nil
leftCapWidth:14.0];
[backButton addTarget:self action:#selector(backButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease];
}
- (void)backButtonTapped:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
The problem is that I need to do it for all my view controllers...
One solution is to put this code in some BasicViewController and all my view controllers will subclass it.
But my question is can I subclass the UINavigationCotroller itself and set it's nab bar left button to this custom button?
The right way to do this is using UIAppearance
It provides methods on UIBarButtonItem such as
- (void)setBackButtonBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics
and
- (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics
No. It would be better to have a custom UIViewController that handles this behavior.
I'm trying to create a custom navigation bar with title and two custom baritems.
What I've done so far:
1. subclass a UINavigationBar
2. override -(void) drawRect:(CGRect)rect method, to draw image as a background
Now I get stuck when making right bar button item.
In my CustomBar class I've overriden pushNavigationItem method as follows:
- (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated {
[super pushNavigationItem:item animated:NO];
item.rightBarButtonItem.customView.frame = CGRectMake(250, 5, 60,30);
}
and in my view controller I've done something like:
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:myButton];
self.navigationController.navigationItem.rightBarButtonItem = barButton;
[self.navigationController.navigationBar pushNavigationItem:self.navigationItem animated:NO]
but I always get SIGABRT when calling
[super pushNavigationItem:item animated:NO];
If I leave that line out, everything runs fine, but there is no button in the navigation bar.
What is the proper way to add custom bar button item to custom navigation bar?
EDIT:
For clarification, I've added an image.
This is what I need.
I'm trying to create the logout button on the right
Have you tried removingnavigationController while setting the item ? I used to do that for setting the title, never used to get the title.
Try [[self navigationItem] setRightBarButtonItem:yourButton];
In your case :
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:myButton];
self.navigationItem.rightBarButtonItem = barButton;`
my application has a UIViewController subclass which is being managed by a UINavigationController.
In the viewDidLoad of my UIViewController subclass, I was attempting to add a UIBarButtonItem to the toolbar like this:
settingsButton = [[UIBarButtonItem alloc] initWithTitle:#"Settings"
style:UIBarButtonItemStylePlain target:self action:#selector(viewSettings:)];
[self setToolbarItems:[NSArray arrayWithObject:settingsButton]];
this wasn't working out for me, so after some googling around, I tried this:
[[self navigationItem] setRightBarButtonItem:settingsButton];
which worked out fine. from reading the UIViewController documentation, I'm still confused about why setToolbarItems wasn't working. I verified in the debugger that the button was in the toolbarItems array in the viewDidAppear method. the button itself just wasn't appearing on my toolbar.
so, my question is, why didn't setToolbarItems work for me in the first code snippet?
I don't have the toolbar configured in my xib for this view controller at all, if that makes a difference.
Yes that make the difference.Whenever you see a bar on view by default for navigation based apps that is not a toolBar actually that is , navigation bar.so you can add item by referencing self.navigationItem.
[self setToolbarItems:[NSArray arrayWithObject:settingsButton]]; essentially populates the navigation controller's bottom toolbar - not the Left and Right top bar buttons.
The bottom toolbar is, by default, not displayed. To display it you must call [self.navigationController setToolbarHidden:NO]
Below is the relevant documentation - UINavigationController Class Reference
toolbar:
The custom toolbar associated with the navigation controller.
(read-only)
#property(nonatomic,readonly) UIToolbar *toolbar Discussion This
property contains a reference to the built-in toolbar managed by the
navigation controller. Access to this toolbar is provided solely for
clients that want to present an action sheet from the toolbar. You
should not modify the UIToolbar object directly.
Management of this toolbar’s contents is done through the custom view
controllers associated with this navigation controller. For each view
controller on the navigation stack, you can assign a custom set of
toolbar items using the setToolbarItems:animated: method of
UIViewController.
The visibility of this toolbar is controlled by the toolbarHidden
property. The toolbar also obeys the hidesBottomBarWhenPushed property
of the currently visible view controller and hides and shows itself
automatically as needed.
try to use
[toolbar setItems:[NSArray arrayWithObject:settingsButton] animated:YES];
instad of :
[self setToolbarItems:[NSArray arrayWithObject:settingsButton]];
shani
On ipad apps, you've got to set toolbar items to the "topViewController" (yes this is counter-intuitive).
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:catView];
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:#"item 1" style:UIBarButtonItemStylePlain target:nil action:nil];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:#"item 2" style:UIBarButtonItemStylePlain target:nil action:nil];
[nav setToolbarHidden:NO animated:YES];
// WRONG: [nav setToolbarItems:[NSArray arrayWithObjects:addButton, nil]];
// CORRECT (for ipad apps):
[nav.topViewController setToolbarItems:[NSArray arrayWithObjects:item1, item2, nil] animated:NO];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:nav];
I have an UITableViewController which I would like to add UIToolbar to with one button. In the
- (void)viewDidLoad;
method of UITableViewController I have:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(pressButton1:)];
self.navigationItem.title = #"Some title";
self.navigationItem.leftBarButtonItem = button;
}
Unfortunately I don't see the toolbar when I run my app.
Any hints? Should I do something more?
The navigationItem property of a view controller is useless if that controller is not displayed inside a UINavigationController.
If your view controller is inside a navigation controller I don't know what the problem is.
Otherwise you can use an UINavigationItem but you need to create a UINavigationBar yourself.
Either in the Interface Builder (add a UINavigationBar and add a UINavigationItem, then connect the UINavigationItem to a property outlet declared your view controller (you don't need to connect the Bar).
Or in your code :
UIBarButtonItem *item = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self action:#selector(pressButton1:)];
UINavigationItem* navItem = [[UINavigationItem alloc] init];
navItem.rightBarButtonItem = item;
navItem.title = #"Your title";
naviBar = [[UINavigationBar alloc] init];
naviBar.items = [NSArray arrayWithObject:navItem];
naviBar.frame = CGRectMake(0.0, 0.0, self.view.frame.size.width, 44.0);
[self.view addSubview:naviBar];
[navItem release];
Your method requires an autorelease:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *button = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(pressButton1:)] autorelease];
self.navigationItem.title = #"Some title";
self.navigationItem.leftBarButtonItem = button;
}
There's nothing wrong with your code per se. Your question states you want to add an UIToolBar to your view? Really? Or do you just want to add a button to the NavigationItem for UITableView?
If you don't have to use a UITableViewController and are not using a UINavigationController in your app already, you can set your view controller up as a regular UIViewController with a toolbar and tableview.
To do this in IB, drag out a UIViewController object and add a toolbar and tableview. Hook up outlets for both and set the delegate and datasource of the tableview to Files Owner. Add any other toolbar items or buttons and give them outlets and methods if you need them for buttons, etc. In your ViewController.h file, make sure you sign it up to conform to the UITableViewDataSource and UITabBarDelegate:
#interface ViewController : UIViewController <UITableViewDataSource, UITabBarDelegate>
From there, just build out your tableview delegate and datasource methods like you normally would, and write your button action methods for any buttons you added to the toolbar.
You just didn't show the toolbar. It is hidden by default. To fix it, you just put this line of code:
self.navigationController.toolbarHidden = NO;
I tried it and it worked. Just make sure that you put in the implementation file's viewDidLoad method.
As shown in the screenshot below, i have a UITableView with some info and upon selecting a row an ABUnknownPersonViewController is invoked. In order to be able to able to dismiss that and go back to the UITableView I have this code:
ABUnknownPersonViewController *unknownPersonView = [[[ABUnknownPersonViewController alloc] init] autorelease];
[unknownPersonView setUnknownPersonViewDelegate:self];
[unknownPersonView setDisplayedPerson:personRecord];
[unknownPersonView setAllowsAddingToAddressBook:YES];
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:#"Επιστροφή" style:UIBarButtonItemStylePlain
target:self action:#selector(goBackToView)];
unknownPersonView.navigationItem.title = #"Προσθήκη στις επαφές";
unknownPersonView.navigationItem.leftBarButtonItem = anotherButton;
navigationController = [[[UINavigationController alloc] initWithRootViewController:unknownPersonView] autorelease];
//navigationController = [[[UINavigationController alloc] initWithRootViewController:self] autorelease];
//self.navigationItem.rightBarButtonItem = anotherButton;
[self presentModalViewController:navigationController animated:YES];
} // didSelectRowAtIndexPath ends here
- (IBAction)goBackToView {
[self dismissModalViewControllerAnimated:YES];
}
- (void)unknownPersonViewController:(ABUnknownPersonViewController *)unknownPersonView didResolveToPerson:(ABRecordRef)person {
// CallerIDAppDelegate *delegate = (CallerIDAppDelegate *)[[UIApplication sharedApplication] delegate];
[navigationController dismissModalViewControllerAnimated:YES];
}
The problem (as you can see) is that when the ABUnknownPersonViewController is dismissed by the "Επιστροφή" button, which is "Back" actually, the view holding the tableView and the blue UIButton is moved a couple of pixels to the bottom!
Any help on what could be causing this?
Screenshot http://dl.getdropbox.com/u/1237004/problem.jpg
Debug this by checking your view's frame in -viewWillAppear, -viewDidAppear, -viewWillDisappear, and -viewDidDisappear.
Also check the view's autoresizingMask, and the parent view's autoresizesSubviews property.
I'm not sure I see the value of setting up a navigation controller here. You could just present the ABUnknownPersonViewController with [self presentModalViewController: unknownPersonView];. If you're doing it for the sake of picking up the visual navigation bar with the back button, then just add a nav bar and button to the unknown person view.
It seems like a mixed metaphor to be creating a UINavigationController but then not using its usual navigation methods (e.g., pushViewController:animated: and popViewControllerAnimated:) and instead using the modal methods inherited from UIViewController.
It seems that adding this line:
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
in my viewWillAppear: made the view not to move when the modal view controller is dismissed. However now the initial position was already slightly dislocated to the bottom but fixed it by moving all the outles in IB to the top so it looks ok.