Hiding UITabBar when pushing a UIView

29,361

Solution 1

This is better:

viewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:viewController animated:YES];

You have to set hidesBottomBarWhenPushed = YES on the controller you are going to push into the view...

Solution 2

when working with storyboard its easy to setup view controller which will hide the tabbar on push, on the destination view controller just select this checkbox:
enter image description here

Solution 3

I've figure out how to get this solved, I was running into the same issue, but Apple also tells us how to do it in the sample called: "The Elements" (http://developer.apple.com/library/ios/#samplecode/TheElements/Introduction/Intro.html)

See function below on how to do it, add this to the init function of the view you want to push in!

-(id) init { 
    if(self = [super init]) { 
        self.hidesBottomBarWhenPushed = YES; 
    } 
    return self; 
}

It will automatically hide the tabbar like the photo app does on your iphone. And when you navigate back the parent view will just show the tabbar again.

Good luck

Solution 4

I have tried most of the suggested solutions. In the end none of them worked for me.

hideTabBarWhenPushed hides the tab bar not only for the view controller that is pushed next but for all view controllers that are pushed within. For those I did want the tab bar controller to re-appear.

Orafaelreis' solution (see above) seemed to suite that most. But his attempt only worked for strict portrait orientations, not even for upside down. So I had to mend it. This is what I finally got:

#define kTabBarHeight               49 // This may be different on retina screens. Frankly, I have not yet tried.

- (void) hideTabBar:(BOOL)hide {

    // fetch the app delegate
    AppDelegate         *delegate   = [[UIApplication sharedApplication] delegate];

    // get the device coordinates
    CGRect              bounds      = [UIScreen mainScreen].bounds;
    float               width;
    float               height;

    // Apparently the tab bar controller's view works with device coordinates  
    // and not with normal view/sub view coordinates
    // Therefore the following statement works for all orientations. 
    width                   = bounds.size.width;
    height                  = bounds.size.height;

    if (hide) {

        // The tab bar should be hidden too. 
        // Otherwise it may flickr up a moment upon rotation or 
        // upon return from detail view controllers. 
        [self.tabBarController.tabBar setHidden:YES];

        // Hiding alone is not sufficient. Hiding alone would leave us with an unusable black
        // bar on the bottom of the size of the tab bar. 
        // We need to enlarge the tab bar controller's view by the height of the tab bar. 
        // Doing so the tab bar, although hidden, appears just beneath the screen. 
        // As the tab bar controller's view works in device coordinations, we need to enlarge 
        // it by the tab bar height in the appropriate direction (height in portrait and width in landscape)
        // and in reverse/upside down orientation we need to shift the area's origin beyond zero. 
        switch (delegate.tabBarController.interfaceOrientation) {
            case UIInterfaceOrientationPortrait:
                // Easy going. Just add the space on the bottom.
                [self.tabBarController.view setFrame:CGRectMake(0,0,width,height+kTabBarHeight)];
                break;

            case UIInterfaceOrientationPortraitUpsideDown:
                // The bottom is now up! Add the appropriate space and shift the rect's origin to y = -49
                [self.tabBarController.view setFrame:CGRectMake(0,-kTabBarHeight,width,height+kTabBarHeight)];
                break;

            case UIInterfaceOrientationLandscapeLeft:
                // Same as Portrait but add the space to the with but the height
                [self.tabBarController.view setFrame:CGRectMake(0,0,width+kTabBarHeight,height)];
                break;

            case UIInterfaceOrientationLandscapeRight:
                // Similar to Upside Down: Add the space and shift the rect. Just use x and with this time
                [self.tabBarController.view setFrame:CGRectMake(0-kTabBarHeight,0,width+kTabBarHeight,height)];
                break;

            default:
                break;
        }
    } else {
        // reset everything to its original state. 
        [self.tabBarController.view setFrame:CGRectMake(0,0,width,height)];
        [self.tabBarController.tabBar setHidden:NO];
    }

    return; 
}


- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{

    // It is important to call this method at all and to call it here and not in willRotateToInterfaceOrientation
    // Otherwise the tab bar will re-appear. 
    [self hideTabBar:YES];

    // You may want to re-arrange any other views according to the new orientation
    // You could, of course, utilize willRotateToInterfaceOrientation instead for your subViews. 
}

- (void)viewWillAppear: (BOOL)animated { 

    // In my app I want to hide the status bar and navigation bar too. 
    // You may not want to do that. If so then skip the next two lines. 
    self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
    [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];

    [self hideTabBar: YES];

    // You may want to re-arrange your subviews here. 
    // Orientation may have changed while detail view controllers were visible. 
    // This method is called upon return from pushed and pulled view controllers.   

    return;
}

- (void)viewWillDisappear: (BOOL)animated {     

    // This method is called while this view controller is pulled
    // or when a sub view controller is pushed and becomes visible
    // Therefore the original settings for the tab bar, navigation bar and status bar need to be re-instated

    [self hideTabBar:NO];

    // If you did not change the appearance of the navigation and status bar in viewWillAppear,
    // then you can skip the next two statements too. 
    self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
    [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];

    return;
}

The in-line comments should explain the reasoning for each statement. Though, there may be smarter ways of coding it.

There is one side effect in conjunction with hiding the status bar and navigation bar too, which I do not want to hide from you guys. 1. When returning from this navigation controller to the calling navigation controller then the status bar and navigation bar on the calling controller overlap until the device is rotated once or until the related tab has been choosen again after another tab came to front. 2. When the calling view controller is a table view and when the device is in landscape mode when returning to the table, then the table is displayed in the appropriate orientation for landscape but it is layed out as if it were portrait. The upper left corner is fine but some table cells plus tab bar are hidden beneath the screen. On the right hand side there is some free space. This, too, is fixed by rotating the device again.

I will keep you updated once I found solutions for these minor but nasty bugs.

Solution 5

Here's how you get this to work:

In the Application Delegate you create the UITabBarController. Then you create a UINavigationController with its root controller as the view controller you want in the particular tab. Then insert the UINavigationController into the "viewControllers" array of the UITabBarController. like so:

ViewControllerForTab1 *tab1Controller = [[ViewControllerForTab1 alloc] initWithNibName:@"ViewControllerForTab1"];

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tab1Controller];

[tab1Controller release];


UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects: navController, nil];

[navController release];


[self.window addSubView:tabBarController.view];

This way you can set the "hidesBottomBarWhenPushed" property to "YES" in any view controller inside that UINavigationController and it will hide the UITabBar.

Hope that helps!

Share:
29,361
Knodel
Author by

Knodel

founder / cto @ timehop

Updated on February 12, 2021

Comments

  • Knodel
    Knodel over 3 years

    I have a UITabBarController where the default view controller is a UINavigationController. I want to be able to hide the UITabBar of the UITabBarController when I push a certain view in the UINavigationController.

    I've tried adding:

    delegate.tabBarController.hidesBottomBarWhenPushed = YES;
    

    in my UINavigationController before I push the view, but that doesn't seem to do the trick.

    Any tips on what I should be doing or if it's even possible? Thanks in advance!

  • givp
    givp over 14 years
    This is definitely better. Thank you!
  • hfossli
    hfossli over 14 years
    that's wrong. both methods should be applied to the view controller you are going to push in..
  • Lukasz
    Lukasz over 13 years
    One thing to remember: you must put above code BEFORE pushing it to the controller. That is just after initialization line. It will NOT work if you put this in viewDidLoad or similar place...
  • Hermann Klecker
    Hermann Klecker over 12 years
    Hiding as such does not work. Well, it does work but it leaves some black background where the tabbar used to be, which is not accessible from my view. Moving the tabbar beyond the visible part of the screen does the trick. However, this does have an impact on the screen's bounds which may have side effects to other parts of the App.
  • Hermann Klecker
    Hermann Klecker over 12 years
    Sorry, the comment above was wrong and I cannot edit it any more. Aparently changing the tabBarController's view's frame does have some impact on the layoout of subViews compared to the (for me insufficient) solution using hidesBottomBarWhenPushed. I am still investigating and may post an update here, unless the error was somewhere in my calculations.
  • Hermann Klecker
    Hermann Klecker over 12 years
    Well, I did observe some side effect that may be of interest: I did nave a small sub view in my view at the very bottom of the full screen. Located assuming that there will be no tab bar and therefore using the space that the tab bar usually occupies. I added this sub view in IB. In IB you stitch each view to one ore more edges or the center of the screen/suberview for autosizing purposes. This sort of automates the orientation change. However, it did re-position my subview along with the tab bar to somewhere below the screen. Just keep the autosizing in mind.
  • Hermann Klecker
    Hermann Klecker over 12 years
    Apologies for the mess. I should not have commented before I finally got it. I will add my solution as a separate answer. My solution is based on yours but is extended to support various orientations plus pushing detail view controllers where the tab bar should re-appear.
  • Enrico Susatyo
    Enrico Susatyo about 9 years
    Thank you very much. I wish Apple added this to the docs, I was so confused.
  • rpgmaker
    rpgmaker about 8 years
    This works great for me. Better than any other solutions so far
  • guru
    guru over 5 years
    I am using the same code above my tabbar is hidden, but my bottom bar looks like animating from up to down.