I have the code below that hides and shows the navigational bar. It is hidden when the first view loads and then hidden when the "children" get called. Trouble is that I cannot find the event/action to trigger it to hide again when they get back to the root view....I have a "test" button on the root page that manually does the action but it is not pretty and I want it to be automatic.
-(void)hideBar {
self.navController.navigationBarHidden = YES;
}
-(void)showBar {
self.navController.navigationBarHidden = NO;
}
Source: Tips4all
The nicest solution I have found is to do the following in the first view controller.
ReplyDelete- (void) viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
[super viewWillDisappear:animated];
}
This will cause the navigation bar to animate in from the left (together with the next view) when you push the next UIViewController on the stack, and animate away to the left (together with the old view), when you press the back button on the NavigationBar.
Please note also that these are not delegate methods, you are overriding UIViewController's implementation of these methods, and according to the documentation you must call the super's implementation somewhere in your implementation.
I would put the code in the viewWillAppear delegate on each view being shown:
ReplyDeleteLike this where you need to hide it:
- (void)viewWillAppear:(BOOL)animated
{
[yourObject hideBar];
}
Like this where you need to show it:
- (void)viewWillAppear:(BOOL)animated
{
[yourObject showBar];
}
One slight tweak I had to make on the other answers is to only unhide the bar in viewWillDisappear if the reason it is disappearing is due to a navigation item being pushed on it. This is because the view can disappear for other reasons.
ReplyDeleteSo I only unhide the bar if this view is no longer the topmost view:
- (void) viewWillDisappear:(BOOL)animated
{
if (self.navigationController.topViewController != self)
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
[super viewWillDisappear:animated];
}
Another approach I found is to set a delegate for the NavigationController and set the NavigationBarHidden value in "navigationController:willShowViewController:animated:"
ReplyDelete- (void)navigationController:(UINavigationController *)navController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
// hide the nav bar if going home
if (viewController == homeViewController) [navController setNavigationBarHidden:YES animated:animated];
else [navController setNavigationBarHidden:NO animated:animated];}
Easy way to customize the behavior for each ViewController all in one place.
After multiple trials here is how I got it working for what I wanted.
ReplyDeleteThis is what I was trying.
- I have a view with a image. and I wanted to have the image go full screen.
- I have a navigation controller with a tabBar too. So i need to hide that too.
- Also, my main requirement was not just hiding, but having a fading effect too while showing and hiding.
This is how I got it working.
Step 1 - I have a image and user taps on that image once. I capture that gesture and push it into the new imageViewController, its in the imageViewController, I want to have full screen image.
- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"Single tap");
ImageViewController *imageViewController =
[[ImageViewController alloc] initWithNibName:@"ImageViewController" bundle:nil];
godImageViewController.imgName = // pass the image.
godImageViewController.hidesBottomBarWhenPushed=YES;// This is important to note.
[self.navigationController pushViewController:godImageViewController animated:YES];
// If I remove the line below, then I get this error. [CALayer retain]: message sent to deallocated instance .
// [godImageViewController release];
}
Step 2 - All these steps below are in the ImageViewController
Step 2.1 - In ViewDidLoad, show the navBar
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(@"viewDidLoad");
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
Step 2.2 - In viewDidAppear, set up a timer task with delay ( I have it set for 1 sec delay). And after the delay, add fading effect. I am using alpha to use fading.
- (void)viewDidAppear:(BOOL)animated
{
NSLog(@"viewDidAppear");
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(fadeScreen) userInfo:nil repeats:NO];
}
- (void)fadeScreen
{
[UIView beginAnimations:nil context:nil]; // begins animation block
[UIView setAnimationDuration:1.95]; // sets animation duration
self.navigationController.navigationBar.alpha = 0.0; // Fades the alpha channel of this view to "0.0" over the animationDuration of "0.75" seconds
[UIView commitAnimations]; // commits the animation block. This Block is done.
}
step 2.3 - Under viewWillAppear, add singleTap gesture to the image and make the navBar translucent.
- (void) viewWillAppear:(BOOL)animated
{
NSLog(@"viewWillAppear");
NSString *path = [[NSBundle mainBundle] pathForResource:self.imgName ofType:@"png"];
UIImage *theImage = [UIImage imageWithContentsOfFile:path];
self.imgView.image = theImage;
// add tap gestures
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[self.imgView addGestureRecognizer:singleTap];
[singleTap release];
// to make the image go full screen
self.navigationController.navigationBar.translucent=YES;
}
- (void)handleTap:(UIGestureRecognizer *)gestureRecognizer
{
NSLog(@"Handle Single tap");
[self finishedFading];
// fade again. You can choose to skip this can add a bool, if you want to fade again when user taps again.
myTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(fadeScreen) userInfo:nil repeats:NO];
}
Step 3 - Finally in viewWill disappear, make sure to put all the stuff back
- (void)viewWillDisappear: (BOOL)animated
{
self.hidesBottomBarWhenPushed = NO;
self.navigationController.navigationBar.translucent=NO;
if (self.navigationController.topViewController != self)
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
[super viewWillDisappear:animated];
}
If what you want is to hide the navigation bar completely in the controller, a much cleaner solution is to, in the root controller, have something like:
ReplyDelete@implementation MainViewController
- (void)viewDidLoad {
self.navigationController.navigationBarHidden=YES;
//...extra code on view load
}
When you push a child view in the controller, the Navigation Bar will remain hidden; if you want to display it just in the child, you'll add the code for displaying it(self.navigationController.navigationBarHidden=NO;) in the viewWillAppear callback, and similarly the code for hiding it on viewWillDisappear
The simplest implementation may be to just have each view controller specify whether its navigation bar is hidden or not in its viewWillAppear:animated: method. The same approach works well for hiding/showing the toolbar as well:
ReplyDelete- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setToolbarHidden:YES/NO animated:animated];
[super viewWillAppear:animated];
}