I am using UISplitViewController with UITabbarController as master view and navigation controller as detail view. Each of the tabs on the master view contain a navigation controller. When any of the tabs on the master view are selected, a view is pushed on the detail view navigation controller.
recentsviewController = [[RecentsViewController_ipad alloc]initWithNibName:#"RootViewController" bundle:nil];
recentsNav = [[UINavigationController alloc] initWithRootViewController:recentsviewController];
//similarly rootNav and favNav
NSArray* controllers = [NSArray arrayWithObjects:recentsNav,self.rootNav,favNav,nil];
self.tabbarController.viewControllers = controllers;
detailViewController=[[LoginViewController_ipad alloc]init];
detailNav=[[UINavigationController alloc]initWithRootViewController:detailViewController];
splitViewController =[[UISplitViewController alloc]init];
splitViewController.viewControllers=[NSArray arrayWithObjects:self.tabbarController,self.detailNav,nil];
splitViewController.delegate = self.detailViewController;
[self.window addSubview:splitViewController.view];
[self.window makeKeyAndVisible];
This seems to work fine. When app goes into portrait mode a 'Browse' button is added to the navigation bar. Clicking this button shows the hidden view along with the tabs perfectly fine. I can switch between the tabs and work on the views displayed in the popover. When tapped on other than popover area the popover is dismissed as expected.
The two things that are not working are
The popover has to show up on its own each time app switches to portrait mode without the user having to select the button added to nav bar
On some occasions I need to dismiss the popover programatically.
I have tried foll code :
- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {
barButtonItem.title = #"Browse";
[[self navigationItem] setLeftBarButtonItem:barButtonItem];
self.appDelegate.rootPopoverButtonItem = barButtonItem;
self.appDelegate.splitViewPopover = pc;
[self.appDelegate.splitViewPopover presentPopoverFromBarButtonItem:self.appDelegate.rootPopoverButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
}
This adds a black translucent popover each time the orientation changes. How do I make it show what the browse button shows when it is clicked?
The usual dismissPopvoerAnimated does not seem to work here.
Any help is appreciated.
Using performSelector:withObject:afterDelay: fixed the issue
Related
For the impatient:
I want to have a navigationcontroller who's root viewcontroller is a tabbarcontroller, similar to the iPad application. I am using IOS 5 and Storyboards.
For the reading inclined:
In my storyboard I have 6 tabs in a UITabBarController that is embeded in a UINavigationController, giving it a "More" button after 3 tabs are shown.
doing so gives me two navigation bars when more is pressed:
So I subclass TabBarController:
//#implentation MyTabController
- (void)viewDidLoad
{
self.moreNavigationController.wantsFullScreenLayout = NO;
self.delegate = self;
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
// hide nav bar if current controller is "More" controller
self.navigationController.navigationBarHidden =
viewController == self.moreNavigationController;
}
Great, this gives me:
My guess was that i needed to relayout the views to account for the statusbar, so i try
[self.view setNeedsLayout:YES];
but i get an error saying UIView does not contain a selector for setNeedsLayout so...
How do I get the moreNavigationController.navigationBar to account for the statusbar?
Update:
I have a second related issue with this. When I hit the "Edit" button the edit controller shows modally. Its navigationbar displays underneath the insured controller (after an animation), and does not receive touches.
Pushing a tabBarController into a NavController isn't recommended, instead set a NavigatorController for every tabBar View controller, and set the TabBarController as the main window root view controller.
If you want to be able to show a screen before showing the tabbar, a solution is to push in all the navigator controllers the previous view controller, followed by the one you want to show (that way all navbars has the backbutton). Then set hidesBottomBarWhenPushed = YES to the first view controller, that way it won't show the tabBar.
Example Code:
UIViewController *prevc = [[UIViewController alloc] init];
//prevc.hidesBottomBarWhenPushed = YES;
//Do this for every VC that will be a tabBarItem
UIViewController *vc1 = [[UIViewController alloc] init];
UINavigationController *nv1 = [[UINavigationController alloc] initWithRootViewController:prevc];
[nv1 pushViewController:vc1 animated:NO];
//Remember to set the tabBarItem!
UITabBarController *tb = [[UITabBarController alloc] init];
tb.viewControllers = [NSArray arrayWithObjects:nv1, nv2, nv3, nil];
I just realized that setting hidesBottomBarWhenPushed to the previous ViewController won't work well, but If you show prevc first, and then push the following viewController, you won't have problems. But if anyway you wan't to hide the tab bar while doing a pop, please check this:
hidesBottomBarWhenPushed but when popped
I have also faced a similar problem. In my application also, there is a Tabarcontroller inside a Navigation controller. When i try to switch to a view controller in more navigation controller programatically (like : [self.tabBarController setSelectedIndex:X]; ) the same issues appears in my application. But the following code solves my problem.
self.tabBarController.moreNavigationController.navigationBarHidden = YES;
I have a button when it pressed, I want it to take me to another view (the "news" view). Within the news view, I want there to be a navigation bar with a back button. I have a navigationcontroller setup throughout my app but I can't seem to get this to work when this button is pressed. It takes me to the view I want but there is no navigation bar and no back button. This is my code that is implemented when the button is pressed.
If anybody know what I am doing wrong, it would be much appreciated.
Thanks
-(IBAction)news
{
newsViewController *view1 = [[newsViewController alloc] initWithNibName:#"newsViewController" bundle:nil];
view1.title=#"news";
[self.navigationController pushViewController:view1 animated:YES];
}
I am not in my mac, so I can not test code, but if it is working and the only issue you got is not show the bar, what you need to is set the bar to be visible:
From apple docs:
The navigation toolbar is hidden by default but you can show it for
your navigation interface by calling the setToolbarHidden:animated:
method of your navigation controller object. If not all of your view
controllers support toolbar items, your delegate object can call this
method to toggle the visibility of the toolbar during subsequent push
and pop operations.
Something like that is supposed to work:
-(IBAction)news {
newsViewController *view1 = [[newsViewController alloc] initWithNibName: #"newsViewController" bundle:nil];
view1.title=#"news";
[self.navigationController pushViewController:view1 animated:YES];
//Add this line!
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
I hope it can help you.
write the below code in page where you want to show navigation controller
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = NO;
}
I Have a TabView control, and when the user clicks on the tab item, the view will load.
When the view is loaded, there is a button on the view, and when i click on the button, another view gets loaded, i used the following code to load the view:
NextView *next = [[NextView alloc]initWithNibName:nil bundle:nil];
[self presentModalViewController:next animated:NO];
But when the view loads, the tab bar items are not displayed. It loads on top of the tab bar items. how can i make the view pop out with the tab bar items ?
NextView *next = [[NextView alloc]initWithNibName:#"yourNibName" bundle:nil];
[self presentModalViewController:next animated:YES];
if you are using presentModalViewController then you can't display the tabBar instead you can use pushViewController
I have a tab bar application and when I display a modal view controller, the content screen is offset by about 20 pixels to the top and left. It looks like this:
I'm presenting this view from the child view controller (detail view) of navigation controller (main view) of the tabview.
When I show the view, I'm hiding the tab bar and navigation bar but status bar is kept visible. Adjusting the view to be centered (through Interface Builder's Simulated Interface Elements->View Mode : Center) and changing the view's frame after a call to 'viewDidLoad' in the controller doesn't seem to shift it.
- (void)viewDidLoad {
// this still doesn't cause it to shift
self.view.frame = CGRectMake(0, 20, 320, 460);
}
What's the way to adjust this so that the content area is shown correctly?
I launch the child view like this:
[detailController presentModalViewController:tvc animated:NO];
The app's view controller hierarchy:
Tab view with two child navigation controllers are created in the app delegate and the nav controllers added to the TabBar's view controllers:
tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:tab1ViewController,
tab2ViewController, nil];
[window addSubview:tabBarController.view];
Each view controllers of the tab is created as a NavigationController with 1 view controller:
// MainViewController inherits from UIViewController
[MainViewController *viewController = [[MainViewController alloc] initWithNib..];
tab1ViewController.viewControllers = [NSArray arrayWithObject:viewController];
A detail view controller is launched with 'pushViewController' as a result of some action on tab1ViewController :
DetailController *detailController = [[DetailController alloc]
initWithNibName:#"DetailView"
bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:detailController animated:YES];
[detailController release];
It's from the detailController that I'm trying to launch the problem controller.
Some things to check right off: is "viewDidLoad" actually getting called?
If so, what is self.view.frame set to after the assignment?
Put an NSLog at the end that prints out the x, y, width, height, and see what's there.
Also, since the trouble vc is modal, it will occupy the entire screen.
"On iPhone and iPod touch devices, the view of modalViewController is always presented full screen."
HTH,
Mike
I'm building an application based on the Utility template from Xcode, to which I have added some more views. My application structure would be as follows:
MainView (the app menu)
Flip-side view (a calculator)
UINavigationController
Settings view
viewDiDLoad: UITabBarController
- Tab1 view (options)
- Tab2 view (information text)
I can navigate correctly from my MainView to my Flip-side view, which is also the root view of the Navigation Controller. From my Flip-side view, I push a second view of my Navigation Controller (Settings view) that is configured to show an UITabBarController, with two tabs, as soon as it loads (with viewDidLoad).
If I remove the UITabBarController, I can return with no problems to my Flip-side view using "popViewController" from my Settings view. The problem comes if I load the UITabBarController in viewDiDLoad in my Settings view... the tabs work perfectly, but I'm not able to return to my Flip-side view (root view of the Navigation Controller) anymore.
I CAN return if I use the Navigation Bar of the Navigation Controller, but I want to configure my own buttons and have the Navigation Bar hidden.
So far I've tried the following methods:
[self.navigationController popViewControllerAnimated:YES];
[self.navigationController popToRootViewControllerAnimated:YES];
[self.navigationController popToViewController:FlipSideViewController animated:YES];
But they don't seem to work. The first two just do nothing (the screen remains as it was), and the third one does not recognize the "FlipsideViewController" (maybe because it's a delegate of the MainViewController?).
Is there a way to check what is exactly doing the "back" button of the Navigation Bar if I activate it?
Should I be using delegates?
Can I call a popViewController method in my Settings view from any of the two Tab views?
This is my Flip-side view:
- (IBAction)showSettingsView {
SettingsViewController *controller = [[SettingsViewController alloc] initWithNibName:#"SettingsView" bundle:nil];
controller.title = #"Settings";
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
This is my Settings view:
- (void)viewDidLoad {
[super viewDidLoad];
tabBarController = [[UITabBarController alloc] init];
Tab1ViewController* vc1 = [[Tab1ViewController alloc] init];
Tab2ViewController* vc2 = [[Tab2ViewController alloc] init];
NSArray* controllers = [NSArray arrayWithObjects:vc1, vc2, nil];
tabBarController.viewControllers = controllers;
[self.view addSubview:tabBarController.view];
}
And the method to return in one of the Tab views:
- (IBAction)backFromTab1View {
[self.navigationController popToViewController:FlipSideViewController animated:YES];
}
Thanks very much and sorry if the question is too basic!
I actually solved the problem creating my own UINavigationBar in the Settings view and using:
[self.view insertSubview:tabBarController.view belowSubview:myNavigationBar];
That inserts the rest of the view below the Navigation Bar and I still can use it to configure a button which pops the view and return to the previous screen.
It took me a while to realise the differences between "addSubview" and "inserSubview + belowSubview". Sorry about that!