I want 2 navigation Controller to be attached to one Tab bar item.
Basically the idea is to have 2 views on a single tab Item and there should be a navigation bar to push and pop the screens. (same like settings application in iPad).
edited======
It will look like on left hand side there is a View with its own navigation Controller and on right hand side there is another View with its own navigation controller(or some other UI) to achieve the Push Pop stuff.
I know how to attach 1 navigation Controller to one Tab bar Item.
Edited For ModalView Issue:-
by implementing conmulligan code everything works property. But if I try to display some ModalViewController in lansdscape mode and when I try to close this ModalView the FirstViewController navigationbar becomes portrait(along with its View) and SecondViewController NavigationBar remains landscape(at it should be). This happens only in Device not in simulator.
Below is my Code of presenting the ModalViewController.
ModalTableViewController *modalTableViewController = [[ModalTableViewController alloc]initWithNibName:#"ModalTableViewController" bundle:[NSBundle mainBundle]];
UINavigationController *localNavigationViewController = [[UINavigationController alloc] initWithRootViewController:modalTableViewController];
localNavigationViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:localNavigationViewController animated:YES];
[modalTableViewController release];
[localNavigationViewController release];
For Dismising the ModalViewCntroller I do it as below:-
[self dismissModalViewControllerAnimated:YES];
Waiting for your replies.
One way would be to create a UIViewController subclass that contains two navigation controllers and add that to the UITabBarController. Here's how you'd create and layout the navigation controllers in the UIViewController's -viewDidLoad method:
FirstViewController *firstViewController = [[FirstViewController alloc] init];
UINavigationController *firstNavigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController];
[firstViewController release];
SecondViewController *secondViewController = [[SecondViewController alloc] init];
UINavigationController *secondNavigationController = [[UINavigationController alloc] initWithRootViewController:secondViewController];
[secondViewController release];
firstNavigationController.view.frame = CGRectMake(0.f, 0.f, 320.f, self.view.frame.size.height);
firstNavigationController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
secondNavigationController.view.frame = CGRectMake(321.f, 0.f, self.view.frame.size.width - 321.f, self.view.frame.size.height);
secondNavigationController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleRightMargin;
[self.view addSubview:firstNavigationController.view];
[self.view addSubview:secondNavigationController.view];
This is more or less how the UISplitViewController works under the hood.
Edit: you might need to add the following code to make sure it lays out properly:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[firstNavigationController viewWillAppear:animated];
[secondNavigationController viewWillAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[firstNavigationController viewWillDisappear:animated];
[secondNavigationController viewWillDisappear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[firstNavigationController viewDidAppear:animated];
[secondNavigationController viewDidAppear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[firstNavigationController viewDidDisappear:animated];
[secondNavigationController viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Related
I have programatically created a TabBarController with views etc. Now i want to show this TabBarController on Button Press. How do i do that? Currently i am presenting it modally but it doesn't work - throws sigtrap errors.
This is my code for the TabBarController
#implementation TabBarViewController
- (void) loadView
{
HomeViewController * homeViewController = [[HomeViewController alloc]initWithNibName:#"HomeViewController" bundle:nil];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.view.frame = CGRectMake(0, 0, 320, 460);
// Set each tab to show an appropriate view controller
[tabBarController setViewControllers:[NSArray arrayWithObjects:homeViewController, homeViewController, nil]];
[self.view addSubview:tabBarController.view];
[homeViewController release];
[tabBarController release];
}
This is my code for accessing this tabBarController from a Button Press event from my mainViewController -
- (IBAction)quickBrowse:(UIButton *)sender
{
TabBarViewController * tabBarController = [[TabBarViewController alloc]init];
[self presentModalViewController:tabBarController animated:YES];
[tabBarController release];
}
You should only override the method loadView if you are not using IB and if you want to create yours view manually. And when you do that you must assign your root view to the view property of UIViewController.
I believe in your case you don't need to override this method, you can use the viewDidLoad method to create your UITabBarController and store it in a variable, so when the event gets called all you need to do is pass the variable to the method presentModalViewController:animated:
Your final code would look like this:
- (void) viewDidLoad
{
[super viewDidLoad];
HomeViewController * homeViewController = [[HomeViewController alloc]initWithNibName:#"HomeViewController" bundle:nil];
// you can't pass the same view controller to more than one position in UITabBarController
HomeViewController * homeViewController2 = [[HomeViewController alloc]initWithNibName:#"HomeViewController" bundle:nil];
// local variable
self.modalTabBarController = [[UITabBarController alloc] init];
// Set each tab to show an appropriate view controller
[self.modalTabBarController setViewControllers:[NSArray arrayWithObjects:homeViewController, homeViewController2, nil]];
}
- (void)viewDidUnload
{
self.modalTabBarController = nil;
[super viewDidUnload];
}
- (IBAction)quickBrowse:(UIButton *)sender
{
[self presentModalViewController:self.modalTabBarController animated:YES];
}
I have this:
FirstViewController:
SecondViewController *secondViewController = [[SecondViewController alloc] init];
[self.navigationController pushViewController:secondViewController animated:YES];
SecondViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES];
}
My problem is that when I comeback from SecondViewController to FirstViewController the NavigationBar is still hidden.Is there a way to make it appear when I'm back in FirstViewController?
In the FirstViewController.m:
-(void)viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO];
}
Yep, it's always possible that a different navigation controller will have set the bar to be hidden. So, in your viewWillAppear set the flag as follows:
self.navigationController.navigationBarHidden = NO;
You need to set [self.navigationController setNavigationBarHidden:NO];
This will do.
I am building an app that has a login screen that leads to a tabbar. I followed this example on how to push a modal view once you launch the app (as the "sign in" page) and then dismiss it.
Example --> Show / Hide tab bar
From some reason, it's not really working - when I launch the app, I see the tabbar view with the two view controllers. no sign in page.
here is my code:
AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController *viewController1 = [[FirstTab alloc] initWithNibName:#"FirstTab" bundle:NSBundle.mainBundle];
UIViewController *viewController2 = [[SecondTab alloc] initWithNibName:#"SecondTab" bundle:NSBundle.mainBundle];
UINavigationController *secondNavController = [[UINavigationController alloc]initWithRootViewController:viewController2];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, secondNavController, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
My first tab (which is where I understand all this modal view business needs to happen)
.h
#interface FirstTab : UIViewController
#end
.m
//UPDATED CODE PER COMMENT BELOW
- (void)viewDidLoad
{
[super viewDidLoad];
SignIn *loginview = [[SignIn alloc] initWithNibName:#"SignIn" bundle:nil];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController: loginview];
self.hidesBottomBarWhenPushed = YES;
[self presentModalViewController:controller animated:YES];
}
And of course, I dismiss the modal view in the SignIn view controller, though I never get there as I mentioned.
What am I doing wrong here? Thanks for the help!!
You could use :
[[self tabBarController] presentModalViewController:controller animated:YES];
since first viewController1 is your first tab, and self.navigationController might be nil.
In your custom view controller subclass called SignIn implement initWithNibName:bundle: instead if init.
-(id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// init here
}
}
Now when init/alloc it call either :
SignIn *loginview = [[SignIn alloc] initWithNibName:#"SignIn" bundle:nil];
if your interface is in a NIB file, or :
SignIn *loginview = [[SignIn alloc] initWithNibName:nil bundle:nil];
if there no NIB.
Also why putting it as a root view controller of any navigation controller ? unless you need to go deeper in some model data presentation, just present it directly :
// why ?
//UINavigationController *controller = [[UINavigationController alloc]
// initWithRootViewController: loginview];
//self.hidesBottomBarWhenPushed = YES;
//[self presentModalViewController:controller animated:YES];
[self presentModalViewController:loginView animated:YES];
You have to include this in your code,
yourModelController =[[Yourmodelcontroller alloc]init];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController: yourModelController];
self.hidesBottomBarWhenPushed = YES;
[[self navigationController] presentModalViewController:controller animated:YES];
[controller release];
hope this will help you out.
I've encountered issues where modals don't like showing from viewDidLoad. Try adding your code to your viewWillAppear and it should show.
I have the following action that gets called when a button gets clicked. The log message gets printed yet, the view doesn't change. This function is in a UIViewController.
Any ideas what I am doing wrong? Why isn't the new view being displayed with a red background?
- (void)viewDidLoad
{
[levelButton2 addTarget:self action:#selector(clickButton) forControlEvents:UIControlEventTouchUpInside];
//MORE CODE
}
- (void) clickButton
{
NSLog(#"Clicked Button");
UIViewController *myViewController = [[UIViewController alloc] init];
myViewController.title = #"My First View";
myViewController.view.backgroundColor = [UIColor redColor];
//to push the UIView.
[self.navigationController pushViewController:myViewController animated:YES];
//[self.navigationController pushViewController:nextController animated:YES];
}
-(void) clickButton
{
NSLog(#"Clicked Button");
MyFirstController *myViewController = [[MyFirstController alloc] init];
[self.navigationController pushViewController:myViewController animated:YES];
[myViewController release];
}
Then after go into the MyFirstController.m file and
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
self.title = #"My First View";
}
return self;
}
I hope it will help you.
You havent used or mention NIB file in that controller..Add NIB file or else make set root view controller of a navigation with a view controller and push the view controller
You have to change your IBAction method a little bit as,
- (void) clickButton
{
NSLog(#"Clicked Button");
MyFirstController *myViewController = [[MyFirstController alloc] initWithNibName:#"MyFirstController" bundle:nil];
myViewController.title = #"My First View";
myViewController.view.backgroundColor = [UIColor redColor];
//to push the UIView.
[self.navigationController pushViewController:myViewController animated:YES];
//[self.navigationController pushViewController:nextController animated:YES];
}
Im my application I have the following code, the first bit runs when my application launches, and it presents a login screen in a modal view. With my rootController added to the window before that.
The Modal view will allow a user to log on, view terms and conditions and then if they accept the loadMainApp function is called.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
rootController.delegate = self;
[window addSubview:rootController.view];
LoginViewController *_loginViewController = [[LoginViewController alloc] initWithNibName:#"LoginView" bundle:[NSBundle mainBundle]];
self.loginViewController = _loginViewController;
[_loginViewController release];
UINavigationController *navi = [[[UINavigationController alloc]initWithRootViewController:loginViewController]autorelease];
navi.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[loginViewController release];
[rootController presentModalViewController:navi animated:YES];
[self.window makeKeyAndVisible];
return YES;
}
This next bit is called when the user accepts terms and conditions:
-(void)loadMainApp:(UIView *)fromView{
[fromView removeFromSuperview];
[window addSubview:rootController.view];
rootController.selectedIndex = 2;
rootController.delegate = self;
}
From here I want to be able to use the people picker which is a modal view and I attempt it with this code:
ABPeoplePickerNavigationController *picker =
[[ABPeoplePickerNavigationController alloc]init];
picker.peoplePickerDelegate = self;
[rootController presentModalViewController:picker animated:YES];
[picker release];
But nothing happens, when I try to present a modal view from my rootController nothing displays.
This appears to occur after this code in applicationDidFinishLaunching is run:
LoginViewController *_loginViewController = [[LoginViewController alloc] initWithNibName:#"LoginView" bundle:[NSBundle mainBundle]];
self.loginViewController = _loginViewController;
[_loginViewController release];
UINavigationController *navi = [[[UINavigationController alloc]initWithRootViewController:loginViewController]autorelease];
navi.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[loginViewController release];
[rootController presentModalViewController:navi animated:YES];
[self.window makeKeyAndVisible];
return YES;
If I dont display the login screen at all and instead just add my rootController
rootController.delegate = self;
[window addSubview:rootController.view];
in the applicationDidFinishLaunching function then everything works fine when I go to display the people picker.
Is there something fundamental that I am breaking here or can anyone spot what I may be doing wrong?
Are you dismissing the first modal view controller correctly, via thedismissModalViewControllerAnimated: method? If you're just removing the modal view controller's view from its superview, then probably a lot of paperwork is being left undone by UIKit.
What you should really do is something like this:
Add rootViewController to navigationController. Then add navigationController to the window.
In rootViewController's viewDidLoad method, set loginViewController's delegate to rootViewController and display the LoginViewController's instance as a modal.
When you are done with terms acceptance, do [delegate loginViewControllerFinished];.
Now in rootViewController, handle the loginViewControllerFinished method. This should contain a call to [self dismissModalViewControllerAnimated:YES]; to close the login modal view. Then you should launch ABPeoplePickerNavigationController as a modal view.
In AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Make sure rootViewController is initiated by this point.
UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];
[window addSubview:rootController.view];
[self.window makeKeyAndVisible];
return YES;
}
In RootViewController:
- (void)viewDidLoad {
[super viewDidLoad];
LoginViewController *loginViewController = [[[LoginViewController alloc] initWithNibName:#"LoginView" bundle:nil] autorelease];
loginViewController.delegate = self;
loginViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:loginViewController animated:YES];
}
- (void)loginViewControllerFinished {
[self dismissModalViewControllerAnimated:YES];
// Here we are closing one modal. And showing another after that.
ABPeoplePickerNavigationController *peoplePicker = [[[ABPeoplePickerNavigationController alloc] init] autorelease];
peoplePicker.peoplePickerDelegate = self;
[self presentModalViewController:peoplePicker animated:YES];
}
In LoginViewController:
// Make sure LoginViewController has delegate property in header.
// #property (nonatomic, assign) id delegate;
// And put this in implementation (.m) file. #synthesize delegate.
// Don't put release for delegate, since it's not retained. It's only 'assigned'.
- (void)done {
// Call this when you want to close loginViewController.
[delegate loginViewControllerFinished];
}
Hope this helps.