I am using my own custom navigationBar, but i need to access it in a number of different views because i need to add buttons, change title and so forth.
Should i pass a reference to my navigationBar each time i show a new view, or just make it a singleton so i can access it from any view?
Neither.
You've listed adding buttons and changing titles as the reasons you need a custom toolbar, but both of those things can be done through the navigation controller with no need to create your own and therefore no need to create a singleton or a global variable.
When you push a new view controller, you can set the title for the navigation bar simply by calling [self setTitle:#"Nav Title"]; in the -viewDidLoad of that view controller. If you need to add a button, use code like the following (also in -viewDidLoad):
[[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemEdit
target:self
action:#selector(setEditing)] autorelease]];
In other words, your design is flawed if you are creating a custom navigation bar only for the reasons you've listed. I suppose there are some good reasons to create a custom navigation bar, but these are not among them.
Consider reviewing the Configuring the Navigation Item Object section of the View Controller Programming Guide for iPhone OS.
Best regards,
Are you using a UINavigationController? If so, you can access the navigation bar from any sub-controller like this:
UINavigationBar *bar = self.navigationController.navigationBar;
Make it a global variable.
Related
So I'm trying to add a UIToolbar to a UIViewController that is part of a UINavigation hierarchy and I was wondering what is the best way to do this. I know in iOS3 they enabled each viewcontroller that is part of a navigation hierarchy to have it's own toolbar so I figure this is the best way to do it. However, the syntax of how I'm doing is bugging me, as I'm using three different types of syntax to add the toolbar as follows:
[[self navigationController] setToolbarHidden:NO];
[self setToolbarItems: myToolbarButtons];
[[[self navigationController] toolbar]setBarStyle:UIBarStyleBlack];
This works fine, and actually fixes a bad memory access from when I was adding the toolbar to the subview of the navigation view. But I don't understand how I can do "self setToolbarItems" after I make the toolbar visible. Does it become a part of the viewcontroller then? Like I said, this works but is bugging me.
An UIVIewController has a property called UINavigationController. Each UINavigationController has a built-in toolbar of their own. So when you are calling,
[[self navigationController] setToolbarHidden:NO];
you are actually enabling the toolbar of the navigationController property that comes with each UIViewController. And when you set the toolbar's item and style with the following two lines:
[self setToolbarItems: myToolbarButtons];
[[[self navigationController] toolbar]setBarStyle:UIBarStyleBlack];
you are actually setting the items of that UINavigationController's built-in toolbar.
Hope this helps. Check out the UIViewController Class Reference for more information.
In line 1 you're sending a message to the toolbar's superview to hide it which is done this way because then the superview can do whatever resizing/layout it wants at the best time.
The navigation controller reads the toolbar from self's variables in line 2, because the navigation controller is currently presenting self.
In line 3 you're accessing the toolbar itself, managed by navigationController. This is a part of the toolbar that relates to itself and not the navigation controller, so the navigation controller doesn't expose ways to modify it, allowing you to access the toolbar directly and then modify it.
This way you are accessing the toolbar at various levels making it easier on yourself. For In the first line you don't have to manage displaying it. In the second and third lines you don't have to manage creating/destroying it.
I am trying to use the UINavigationController object's built-in UIToolbar object in my iPad application, but I want it to be displayed on top of the view instead of the bottom, which is where it defaults.
I am also hiding the UINavigationController object's Navigation Bar.
In order to make this work, I had to write the following code:
navigationController.navigationBarHidden = YES;
navigationController.toolbarHidden = NO;
navigationController.toolbar.frame = CGRectMake(0, 0, 768, 44);
This solution works with one exception: when the application Enters Background and Becomes Active again, the Toolbar is always repositioned on the bottom of the view.
I've tried moving the code from viewDidLoad to viewDidAppear:animated, and it still behaves this way.
First, is there any better way to approach this, and if not, how can I stop the Toolbar from being repositioned?
I've also instead decided to use my own UIToolbar object and add it to each view via a custom Base UIViewController class' viewDidLoad. However, this causes the Toolbar to animate when each view is pushed or popped because it is actually part of the view, which just seems "hokey".
Any ideas on possible solutions?
Thanks everyone!
It says in the documentation under UINavigationController's toolbar property that:
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.
This is sort of hackish, but you could make a UIToolbar yourself and add it directly to the window (i.e. over the navigation controller.)
You can use the category below to modify the UIToolbar class to achieve what you're after.
#implementation UIToolbar (setCenter)
-(void)setCenter:(CGPoint)center
[super setCenter:CGPointMake(384, 22)];
}
#end
The toolbar has limited functionality when used with a UINavigationController. It only provides a convenient way to manage the actionsheet in the toolbar.
From the docs: "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."
The solution I would use is to create a subclass of UIView with convenience methods to manage your actionsheet and any other custom functionality you need. This custom view can be shared across all views in the UINavigationController and placed where ever you like in the parent view. This will give you ultimate control of your custom top placed toolbar.
I want to duplicate this controller same functionality without using it, this is because tab bar controllers are not customizable at all (fixed size, toggleable state tabs, etc...).
I want a customized "tab bar" that contains whichever view I want. And also I need to push view controllers leaving this customized tab bar fixed in its position.
I´ve seen lots off apps that do this, and I was wondering if using different UIWindow objects (one for the custom tab bar and other one for the content) was the best approach.
Any advice or guidance on this?
Thanks in advance.
Definitely not UIWindows - in an iPhone app there should only ever be one UIWindow.
I'd make a UIViewController subclass that had your new navigation bar ui at the top and a UIView underneath it. This view would be used to contain all the views of the controllers you are going to push in it. The view would have clipsToBounds set to YES to make sure your other controllers views don't overlap your navigation bar etc.
It would also have an array to hold the list of controllers that are currently inside it.
Your controller would implement the pushViewController:animated: methods etc to allow you to add other view controllers to the stack - you would add the new controller to your array and would add it's view as a subview of your controller's view.
However, it's actually quite a lot of work to make this well - a navigation controller will release child controller views on low memory warnings, handle rotation, animating on/off views etc. Are you 100% sure that this is what you want to do?
I've used a very simple approach. I subclass UITabbarController and during the init:
// Custom TabBar View
//
self.tabBar.hidden = YES;
MyTabBarView *myTabBarView = [[MyTabBarView alloc] initWithFrame:CGRectMake(0, 1024-44, 768, 44) // it'a an iPad app
configuration:configuration]; // an array of dictionary representing the view controllers
[self.view addSubview:myTabBarView];
[bottomBarView release];
then I load some view controllers with:
aViewController.hidesBottomBarWhenPushed = YES;
From MyTabBarView instance I perform on the UITabBarViewController:
setSelectedIndex:
In this way I've a customizable full screen application without pains.
I am trying to build an iPhone application that has a Tab bar as the root controller and several navigation bars. My doubt is, shall I create one NavigationBarController class for each navigation bar that I want to put in the application? Or is it possible to create only a single navigation controller that manages all the navigation bar controllers that exist in the application?
In the case that multiple navigation controllers exist in the application, can I use the "self" to access the correct navigation controller that pushes/pops the view? Or should I use the delegate of the Application delegate to access each navigation bar controllers?
(I am assuming that all navigation bar controllers are declared in the application delegate, is this approach correct or is there a more elegant approach?)
Thanks a lot in advance
The common way to achieve this is to create a Tab Bar application and then change each item in the tab bar to be a UINavigationController. If you do this, you can definitely use self to access the navigationController - specifically you can use self.navigationController.
Watch out for possible leak in this part of the above code:
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tools];
You could use this instead:
UIBarButtonItem* rightButtonBar = [[UIBarButtonItem alloc] initWithCustomView:tools];
self.navigationItem.rightBarButtonItem = rightButtonBar;
[rightButtonBar release];
;) ... or use autorelease
Insert a unique UINavigationController for each tab.
You can't have a single controller manage across multiple tabs, since a navigation controller can only have a single linear stack of view controllers. Each tab should have it's own navigation controller with a different root controller in each one.
The common way to achieve this is to create a Tab Bar application and
then change each item in the tab bar to be a UINavigationController.
This is THE way of achieving this. I have loaded 5 navigation controllers into a tab bar controllor. The key tip is to plan the navigations of the App, as every navController should take place where a new navigation tree starts.
Here is my problem:
I've read a lot about how to use a tab bar within a navigation based application, but i still can't figure it out. I have tried both to use and avoid using a tab bar controller, but i just can't find the solution.
I already have a navigation based app working. I have several nib files (views), each one with its own view controller, that i programmatically push onto the navigation controller stack. I need one of this views to have a tab bar that allows me to switch between some of the others. I understand how the tab bar works, and i do think what i need is to use a tab bar controller, since it would allow me to define the view controllers associated with each tab bar item, and manage all about them. However, i can't see how to do it.
If i do declare a tab bar controller in my "tabBarViewController", draw the tab bar controller in my "tabBarView" and link them with the IB, it will give me an error (I reckon this is because i haven't really pushed the tab bar controller's view? do i need something equivalent to "[window addSubView:[tabbarcontroller view]]?). In this case, all i need to know is how to "see" the tab bar controller's top view controller's view within a view controller i have already pushed.
If i try not to use a tab bar controller, as i have read is the best solution to this problem, ¿how do i manage tab bar items, the switchs between them, etc?
I would really appreciate your help.
You can't push a tab bar controller onto a navigation controller stack. There's just no supported way to do it.
What you may want to consider instead is creating your own instance of UITabBar, then using a delegate that conforms to UITabBarDelegate. That way, your delegate will receive the tabBar:didSelectItem: message whenever a tab bar item is selected by the user. You'll have to manage the NSArray of items for the bar yourself, though, without using IB.
Once you've got that figured out, all that's left to do is push a regular UIViewController onto your navigation stack like any other, and just have that controller manage your tab bar and delegate.
I just made an App with a tabBar controller and 5 navControllers. All you need to do is load the nibs and navigation controller inside the first element of the tabBar controller. You can HIDE the tabBar even if the views are inside it, and make it appear in the view you need it to.
You can do this with a bit of code, like so:
FooViewController *foo = [[FooViewController alloc] init];
BarViewController *bar = [[BarViewController alloc] init];
UITabBarController *tabby = [[UITabBarController alloc] init];
[tabby setViewControllers:[NSArray arrayWithObjects:foo, bar, nil] animated:NO];
[self.navigationController pushViewController:tabby animated:YES];
[foo release];
[bar release];
[tabby release];
You could probably do it with IB as well, just load the tab bar controller from a nib.
I built a sample project that demonstrates this in action, you can download it from http://s3.thismoment.com/navtab.zip