I have the following in the mainwindow.xib
Navigation Controller
List item
Tab bar controller
tabbar
firstViewController
SecondViewController
The entrypoint
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
navController.viewControllers = [NSArray arrayWithObject:tabBarController];
[window addSubview:navController.view];
[window makeKeyAndVisible];
return YES;
}
and now in the first viewcontroller i'm writing
-(void)loadView
{
if(rootAppDelegate==nil)
rootAppDelegate=(tabbarAppDelegate *) [[UIApplication sharedApplication]delegate];
listEmergencyItems= rootAppDelegate.listOfEmergencySectionItems;
self.rootAppDelegate.navController.navigationBarHidden = NO;
[super loadView];
}
and in the second viewcontroller i'm writing
- (void)loadView
{
if(rootAppDelegate==nil){
rootAppDelegate=(tabbarAppDelegate *) [[UIApplication sharedApplication]delegate];
}
listHospitalsItems= self.rootAppDelegate.listOfHospitalsItems;
self.rootAppDelegate.navController.navigationBarHidden = YES;
[super loadView];
}
And on the runtime, when it first loads the first view, i see the navigationbar where i need to navigate into a detail view.
And when i press the second tab bar item, i go to the second view, and the navigation bar gets hidden.
But when i press back on the first tabbar item, i.e. returning to the first viewcontroller. the navigation bar remains hidden.
Any idea?
The navigation bar won't show in the second view because neither view was placed on the navigationcontroller's stack. you want to use something like this in the parent to present a child view instead of overriding loadView
ViewToPresentViewController *myVController = [[ViewToPresentViewController alloc] initWithNibName:#"ViewToPresentViewController"
bundle:nil];
myVController.property = someValue;
[self.navigationController pushViewController:myVController
animated:YES];
[myVController release];
then, as i said previously, you can just use [self.navigationController setNavigationBarHidden:animated:]
Related
I have a tab bar item which is connected navigation controller with a UIViewController as the root view controller. The first touch on the tab bar item switches to that view. The second touch pops to the root view controller. The third touch does not scroll to the top.
I've seen this scroll-to-top behavior in other apps, but after searching the webs, I cannot find out anything about it.
Is this default behavior for scroll views or table views attached to tab bar items, or is it something I need to implement myself?
I realize this is an older question, but I'm also looking to create this behavior, and I think I have a simpler solution.
First, set your AppDelegate to be the delegate for your UITabBarController. Then add this method to AppDelegate.m:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if ([tabBarController.viewControllers objectAtIndex:tabBarController.selectedIndex]==viewController)
{
if ([viewController isKindOfClass:[UITableViewController class]])
{
[[(UITableViewController *)viewController tableView] setContentOffset:CGPointZero animated:YES];
}
else if ([viewController isKindOfClass:[UINavigationController class]])
{
UINavigationController *nav = (UINavigationController *)viewController;
if ([nav.visibleViewController isKindOfClass:[UITableViewController class]])
[[(UITableViewController *)nav.visibleViewController tableView] setContentOffset:CGPointZero animated:YES];
}
}
return YES;
}
This works if your tab points at a UITableViewController or at a UINavigationController with a UITableViewController as the root view, and you don't have to worry about distinguishing between which UITableViewController is affected, sending notifications, etc.
Here is the solution to scroll to top of the table view when tab bar is clicked
In AppDelegate set tabbar delegate
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if (tabBarController.selectedIndex == 0) {
UINavigationController *selectedNav = [self.tabBarController.viewControllers objectAtIndex:self.tabBarController.selectedIndex];
UIViewController *currentVC = selectedNav.visibleViewController;
if([currentVC isMemberOfClass:NSClassFromString(#"HomeViewController")])
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshView" object:nil];
}
}
return YES;
}
In HomeViewController.m view did load listen for the notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshView:)
name:#"refreshView"
object:nil];
Refresh method
-(void)refreshView:(NSNotification *) notification{
if (self == self.navigationController.topViewController)
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}
No, this isn't default behaviour, you have to implement it yourself.
I'd do it by making the application delegate the delegate of the tab bar controller, and implement -tabBarController:didSelectViewController: to post a notification. Listen for that notification in your table view controller and do something like:
if (self == self.navigationController.topViewController)
[self.tableView scrollToTop];
Since your tab controller can only have one delegate, you may want to look at the answer to this question, which describes how to listen for the tap using KVO.
I push a ViewController on my UINavigationController, but I see no 'back' button... the NavBar is empty but there.
In my storyboard, my initial View Controller is the NavigationController, and I set the 'Top Bar' to 'None' in the Simulated Metrics section. When I switch to Inferred or Navigation Bar, everything work ok, I see the back button with text "back". (but then all my View are ugly since I removed the NavBar for a reason).
How could I preserve my design (NavBar hidden/not there) and be able to push a new ViewController with a NavBar and Back button. NavBar on demand!
Thanks
Found a solution: just put my AppDelegate as the UINavigationController delegate and manually hide/show the NavBar.
In my Storyboard, the navigation controller is with:
Simulated Metrics -> Top Bar -> None
Navigation Controller -> Bar Visibility -> uncheck "Shows Navigation
Bar"
The AppDelegate .h/.m:
#interface AppDelegate : UIResponder <UIApplicationDelegate, UINavigationControllerDelegate>
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (something) {
navigationController.navigationBarHidden = TRUE;
}
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (somethingElse) {
navigationController.navigationBarHidden = FALSE;
}
}
You want to configure navigation in application
try this in ApplicationDidFinishLoading Method in App delegate
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[window makeKeyAndVisible];
[window addSubview:navController.view];
after use this to change view in action method of button
DetailViewController *ViewController = [[DetailViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushNavigationController:ViewController animated:YES];
I have the right view selected from my PopOver but instead of showing in Parent View it is showing in PopOverView.
Here are some screenshots:
After I select the Feedback option instead showing the view in my parentview which in my case is SecondViewController (grey background screen) it is showing in the PopOver itself.
For information I have Three VC's namely FirstViewController, SecondViewController and ThirdViewController each assigned to each TabBar item. I want to make SecondViewController as parent for the PopOver.
Here is my code where I create PopOver in my AppDelegate.m
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if([viewController isKindOfClass:[SecondViewController class]]){
NSInteger index = [[self tabBarController] selectedIndex];
CGRect buttonFrame = [[[[[self tabBarController] tabBar] subviews] objectAtIndex:index+1] frame];
PopOverViewController *popoverContentController = [[PopOverViewController alloc]init];
UINavigationController *navcon = [[UINavigationController alloc]initWithRootViewController:popoverContentController];
popoverContentController.contentSizeForViewInPopover = CGSizeMake(250, 85);
popover = [[UIPopoverController alloc]initWithContentViewController:navcon];
NSLog(#"X:%f Y:%f",buttonFrame.origin.x,buttonFrame.origin.y);
[popover presentPopoverFromRect:buttonFrame inView:self.tabBarController.tabBar permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
}
And the code in my PopOverController.m where I am making a choice of which new view to show
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
sendFeedback *sendEmailViewController = [[sendFeedback alloc]initWithNibName:#"sendFeedback" bundle:nil];
downLoad *downloadFilelViewController = [[downLoad alloc]initWithNibName:#"downLoad" bundle:nil];
if (indexPath.row == 0)
[self.navigationController pushViewController:sendEmailViewController animated:YES];
else
[self.navigationController pushViewController:downloadFilelViewController animated:YES];
}
Can anyone let me know how I can make the reference to my parent view (SecondViewcontroller) so that the new view shows in my parent view rather than the popover view.
Thanks
You insert into popover UINavigationController and in didSelectRowAtIndexPath push newly created controller to existed stack (into popover UINavigationController), but not into tab bar.
In order to push newly created controller to second tab you need to assign second tab (now it is SecondViewController) to new UINavigationController and use exactly this navigation stack.
Code will look like this:
UINavigationController *navController = (UINavigationController*)[tabBarController.viewControllers objectAtIndex:1];
[navController pushViewController:downloadFilelViewController animated:YES];
I've I have a simple noob question, I would like to hide the navigation bar of a UINavigationController, but I'm pretty sure I`m not calling the right object .
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIViewController *rootViewController = [[[TestViewController alloc] init] autorelease];
viewController = [ [UINavigationController alloc] initWithRootViewController:rootViewController];
[window addSubview:viewController.view];
[window addSubview: rootViewController.view];
[window makeKeyAndVisible];
return YES;
}
Now, I`ve tried, this :
-(void)hideBar {
viewController.navigationBarHidden = YES;
}
It is complaining that "navigationBarHidden" not found on object type UIViewController, obviously I would need to call the UINavigation controller instead, but that's where I'm stuck ...
Try:
[self.navigationController setNavigationBarHidden:YES];
within your TestViewController. A good place is in viewDidLoad
Also, while we're at it, remove the line [window addSubview:rootViewController.view];, you don't need it.
In Navigation controller's root view controller's method viewDidLoad write this -
[self.navigationController setNavigationBarHidden:TRUE];
in your case its TestViewController.
I have a UINavigationController setup in my AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add the navigation controller's view to the window and display.
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
In my RootViewController I am pushing another view onto the stack:
//Show the deals
DealViewController *dvc = [[DealViewController alloc] initWithNibName:#"DealViewController" bundle:nil];
[self.navigationController.navigationBar setHidden:NO];
[self.navigationController pushViewController:dvc animated:YES];
The view shows up, but there is no back button that is added to my navigation bar. Why is this and how can I resolve it?
Are you setting self.title in RootViewController? Perhaps the UINavigationController doesn't have any text to put on the back button, so it omits it...?
Are you setting hidesBackButton = YES or backBarButtonItem = nil in DealViewController, or does it have a different leftBarButtonItem defined?
Try this:
DetailViewController *detailViewController = [[DetailViewController alloc] init];
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithTitle : #"Back"
style : UIBarButtonItemStyleDone
target : nil
action : nil];
self.navigationItem.backBarButtonItem = back;
[self.navigationController pushViewController : detailViewController animated : YES];
[detailViewController release];
You must think of the navigation controller as a stack of navigation controllers each controlling one screen full of information.
You instantiate the navigation controller with the
-(id)initWithRootViewController:(UIViewController *)rootViewController
method. You specify the root view controller in this call. Then you add the navigation controller's view as a subview to the window, like you did before.
If you want to show your second screen you push another view controller on the stack by using
-(void)pushViewController:detailViewController animated:YES
method.
Using presentModalViewController to show the naviagtionController. Set the navagitionController bar button like so:
[navigationController.navigationBar.topItem setLeftBarButtonItem:
[[[UIBarButtonItem alloc] initWithTitle: #"Back"
style: UIBarButtonItemStylePlain
target: self
action: #selector(dismisstheModal:)] autorelease]];
This happened to me because in my navigation controller's content controller I had set up some navigation controller behavior in viewDidLoad and in another class that inherits from my content controller, and the one that was being presented, i implemented a viewDidLoad as well, and forgot to call [super viewDidLoad] which thereby caused me to override the base class's viewDidLoad where I was setting up my navigation controller buttons. Oooops.