How to hide uitabbarcontroller

IphoneIosUitabbarcontroller

Iphone Problem Overview


I have a problem with UITabBarController. In my application, I want to hide it but without using hidesBottomBarWhenPushed because I want to hide it not when I pushed it. For Example, I want to hide it when I press a Hide button in my application.

I read many articles in google but I cant find out how I can do this.

Iphone Solutions


Solution 1 - Iphone

I am pasting this from my working code... you can call these methods to hide and show the tabbarcontroller.... just pass tabbarcontroller instance to these functions..

// Method call
[self hideTabBar:self.tabBarController];   

// Method implementations
- (void)hideTabBar:(UITabBarController *) tabbarcontroller
{
	[UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    
    for(UIView *view in tabbarcontroller.view.subviews)
    {
		if([view isKindOfClass:[UITabBar class]])
        {
			[view setFrame:CGRectMake(view.frame.origin.x, 480, view.frame.size.width, view.frame.size.height)];
        } 
		else 
		{
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
        }
    }
	
    [UIView commitAnimations];	 
}

- (void)showTabBar:(UITabBarController *) tabbarcontroller
{   	
	[UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    for(UIView *view in tabbarcontroller.view.subviews)
    {
        NSLog(@"%@", view);
		
        if([view isKindOfClass:[UITabBar class]])
        {
			[view setFrame:CGRectMake(view.frame.origin.x, 431, view.frame.size.width, view.frame.size.height)];
			
        } 
        else 
        {
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 431)];
        }
    }
	
    [UIView commitAnimations]; 
}

Solution 2 - Iphone

Modified Setomidor's answer to work on both landscape, portrait, and iPad (the 320 and 480 values only work on iPhone).

- (void) hideTabBar:(UITabBarController *) tabbarcontroller 
{
	CGRect screenRect = [[UIScreen mainScreen] bounds];
	
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
	float fHeight = screenRect.size.height;
	if(  UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
	{
		fHeight = screenRect.size.width;
	}

    for(UIView *view in tabbarcontroller.view.subviews)
    {
		if([view isKindOfClass:[UITabBar class]])
        {
            [view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
        } 
        else 
        {
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
			view.backgroundColor = [UIColor blackColor];
        }
    }
    [UIView commitAnimations];
}



- (void) showTabBar:(UITabBarController *) tabbarcontroller 
{	
	CGRect screenRect = [[UIScreen mainScreen] bounds];
	float fHeight = screenRect.size.height - tabbarcontroller.tabBar.frame.size.height;
	
	if(  UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
	{
		fHeight = screenRect.size.width - tabbarcontroller.tabBar.frame.size.height;
	}
	
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    for(UIView *view in tabbarcontroller.view.subviews)
    {	
        if([view isKindOfClass:[UITabBar class]])
        {
            [view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];			
        } 
        else 
        {
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
        }		
    }
    [UIView commitAnimations]; 
}

Also modified the code to handle changes introduced in iOS 6 with UIDevice orientation change and ensure that it works properly even when the device is lying on its back.

Solution 3 - Iphone

In your action method for the button:

[self.tabBarController.tabBar setHidden:YES];

Solution 4 - Iphone

Saurahb and karlbecker_com's solutions are great, though they can cause an obvious popping effect when the view contains a tableview while the tab bar animates back up. I've made some modifications and combined it into a single function (as a category on UITabBarController). It's not completely perfect (delayed correction animation) but gives good results with tables.

If you like animation blocks and categories, give this a try. Orientation and device friendly.

UITabBarController+ShowHideBar.m:

#import "UITabBarController+ShowHideBar.h"

@implementation UITabBarController (ShowHideBar)

- (void) setHidden:(BOOL)hidden{

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    float fHeight = screenRect.size.height;
    if(  UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) ){
        fHeight = screenRect.size.width;
    }

    if(!hidden) fHeight -= self.tabBar.frame.size.height;

    [UIView animateWithDuration:0.25 animations:^{
        for(UIView *view in self.view.subviews){
            if([view isKindOfClass:[UITabBar class]]){
                [view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
            }else{
                if(hidden) [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
            }
        }
    }completion:^(BOOL finished){
        if(!hidden){

            [UIView animateWithDuration:0.25 animations:^{

                for(UIView *view in self.view.subviews)
                {
                    if(![view isKindOfClass:[UITabBar class]])
                        [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
                }

            }];
        }
    }];
 
}

@end

UITabBarController+ShowHideBar.h:

#import <UIKit/UIKit.h>

@interface UITabBarController (ShowHideBar)

- (void) setHidden:(BOOL)hidden;

@end

Usage:

[self.tabBarController setHidden:YES];
[self.tabBarController setHidden:NO];

Solution 5 - Iphone

Saurabh's answer above can be extended to also work in landscape orientation:

+ (void) hideTabBar:(UITabBarController *) tabbarcontroller {

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];

    //Support for landscape views
    int orientation = [[UIDevice currentDevice] orientation];
    int x_pos = 480;
    if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
        x_pos = 320;
    }

    for(UIView *view in tabbarcontroller.view.subviews)
    {
        if([view isKindOfClass:[UITabBar class]])
        {
            [view setFrame:CGRectMake(view.frame.origin.x, x_pos, view.frame.size.width, view.frame.size.height)];
        } 
        else 
        {
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, x_pos)];
        }       
    }   
    [UIView commitAnimations]; 
}

`

The corresponding x_pos numbers for showTabBar() are 431 and 271.

Solution 6 - Iphone

This is karlbecker_com's answer, ported to MonoTouch (Xamarin.iOS). The only difference is that I implemented the methods on a class that inherits from UITabBarController, so references to "tabbarcontroller" were replaced by "this".

public void HideTabBar()
{
	var screenRect = UIScreen.MainScreen.Bounds;
	float fHeight = screenRect.Height;
	if(UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft
	   || UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight)
	{
		fHeight = screenRect.Width;
	}
	
	UIView.BeginAnimations(null);
	UIView.SetAnimationDuration(0.4);
	foreach(UIView view in this.View.Subviews)
	{
		if(view is UITabBar)
		{
			view.Frame = new RectangleF(view.Frame.X, fHeight, view.Frame.Width, view.Frame.Height);
		} 
		else 
		{
			view.Frame = new RectangleF(view.Frame.X, view.Frame.Y, view.Frame.Width, fHeight);
			view.BackgroundColor = UIColor.Black;
		}
	}
	UIView.CommitAnimations();
}

public void ShowTabBar()
{   
	var screenRect = UIScreen.MainScreen.Bounds;
	float fHeight = screenRect.Height - 49f;
	if(UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft
	   || UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight)
	{
		fHeight = screenRect.Width - 49f;
	}
	
	UIView.BeginAnimations(null);
	UIView.SetAnimationDuration(0.4);
	foreach(UIView view in this.View.Subviews)
	{
		if(view is UITabBar)
		{
			view.Frame = new RectangleF(view.Frame.X, fHeight, view.Frame.Width, view.Frame.Height);
		} 
		else 
		{
			view.Frame = new RectangleF(view.Frame.X, view.Frame.Y, view.Frame.Width, fHeight);
		}
	}
	UIView.CommitAnimations();
}

Solution 7 - Iphone

@karlbecker_com Answer works perfect for both the iPhone 4 and iPhone 5. If anyone is having issues with iOS7 black bar at the bottom set the tabBarController to translucent

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

// To Hide the black line in IOS7 only, this extra bit is required
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
    [self.tabBarController.tabBar setTranslucent:YES];
}  

Solution 8 - Iphone

Since IOS 7.1, "Swift" solutions:

self.tabBarController?.tabBar.hidden = true // hide tabbar
self.tabBarController?.tabBar.hidden = false // show tabbar

Hope this could help!

Solution 9 - Iphone

you can push a modal view controller

[self presentModalViewController:myFullscreenViewController animated:YES];

this will create a completely new view fullscreen above your current one.

dismiss ist with dismissModalViewController:animated:

Solution 10 - Iphone

The solution below works fine for me in exactly the same use case where I have to move to fullscreen mode with TabBar animation.

Basically, the idea is

  1. to make a snapshot of UITabBar;

  2. add the UIImage of the snapshot to UIImageView which has the same frame as UITabBar does;

  3. resize underlying view and place it on self.tabBarController.view;

  4. set UITabBar's alpha to be 0.0;

  5. place the UIImageView with UITabBar's snapshot on the self.tabBarController.view;

  6. Once the above is achieved, do any kind of animation

     #import "QuartzCore/CALayer.h"
     
     @implementation FTBFirstViewController {
        BOOL hidden;
        UIImageView *fakeTabBarImageView;
        UIView *viewToResize;
     }
    
     - (void)viewDidLoad
     {
         [super viewDidLoad];
    
         //////////////////////////////
         // Create your viewToResize
         //////////////////////////////
         [self.view addSubview:viewToResize];
    
         hidden = NO;
     }
    
     - (void)hideTabBar:(id)sender {
         if (!hidden) {
             //
             // to create the fake UITabBar
             fakeTabBarImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
             UIImage *fakeTabBarImage = [self imageScreenshotFromView:self.tabBarController.tabBar];
             fakeTabBarImageView.image = fakeTabBarImage;
             fakeTabBarImageView.frame = self.tabBarController.tabBar.frame;
             //
             // to resize underlying UIView
             viewToResize.frame = (CGRect){viewToResize.frame.origin.x, viewToResize.frame.origin.y + 20.f, viewToResize.frame.size.width, viewToResize.frame.size.height + fakeTabBarImageView.frame.size.height};
             //
             // to hide real UITabBar
             self.tabBarController.tabBar.alpha = 0.0;
             //
             // to add views in exactly this order
             [self.tabBarController.view addSubview:viewToResize];
             [self.tabBarController.view addSubview:fakeTabBarImageView];
             //
             // do any sort of animation
             [UIView animateWithDuration:0.8 animations:^{
                 fakeTabBarImageView.frame = (CGRect){fakeTabBarImageView.frame.origin.x, fakeTabBarImageView.frame.origin.y + fakeTabBarImageView.frame.size.height, fakeTabBarImageView.frame.size};
             }];
         
             hidden = YES;
         } else {
             [UIView animateWithDuration:0.8 animations:^{
                     fakeTabBarImageView.frame = (CGRect){fakeTabBarImageView.frame.origin.x, fakeTabBarImageView.frame.origin.y - fakeTabBarImageView.frame.size.height, fakeTabBarImageView.frame.size};
             } completion:^(BOOL complete){
                 self.tabBarController.tabBar.alpha = 1.0;
                 [fakeTabBarImageView removeFromSuperview];
                 fakeTabBarImageView = nil;
    
                 viewToResize.frame = self.view.frame;
                 [self.view addSubview:viewToResize];
             
                 [fakeTabBarImageView removeFromSuperview];
             }]; 
             
             hidden = NO;
         }
     }
    
     - (UIImage *)imageScreenshotFromView:(UIView *)aView {
         UIImage *viewImage;
         
         UIGraphicsBeginImageContextWithOptions(aView.bounds.size, aView.opaque, [[UIScreen mainScreen] scale]);
         [aView.layer renderInContext:UIGraphicsGetCurrentContext()];
         viewImage = UIGraphicsGetImageFromCurrentImageContext();
         UIGraphicsEndImageContext();
     
         return viewImage;
     }
    

Solution 11 - Iphone

I tried pretty much all these answers but none of them worked for me. My app has a UITabBarController as the root view, and each tab has a UINavigationController. One of the UINavigationControllers has a UICollectionViewController as the top view controller. When the user selects an item in the UICollectionView, I wanted the detail view controller to get pushed onto the navigation stack. My detail view then had a toolbar at the bottom. I didn't want the toolbar to appear on top of the tab bar as that looks goofy, and switching tab contexts won't be needed from this view. I could probably have easily solved this by manually placing UIToolbars and UITabBars and not using UITabBarController and the built-in UIToolbar, but that seemed like too much refactoring and a bit inelegant.

In the end my solution was fairly simple: extend the bounds of the UITabBarController off the bottom of the screen. I added this to my detail view controller:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    // Extend the UITabBarController to shift the tab bar off screen
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGRect tabBarControllerFrame = self.tabBarController.view.frame;
    if (animated) {
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.5];
        tabBarControllerFrame.size.height = screenRect.size.height +
            self.tabBarController.tabBar.frame.size.height;
        [self.tabBarController.view setFrame:tabBarControllerFrame];
        [UIView commitAnimations];
    }
    else {
        tabBarControllerFrame.size.height = screenRect.size.height +
            self.tabBarController.tabBar.frame.size.height;
        [self.tabBarController.view setFrame:tabBarControllerFrame];
    }
    
    // Now show the toolbar
    [self.navigationController setToolbarHidden:NO animated:animated];
}

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    
    // Ensure the UITabBarController remains extended when subviews are laid out
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGRect tabBarControllerFrame = self.tabBarController.view.frame;
    tabBarControllerFrame.size.height = screenRect.size.height + 
        self.tabBarController.tabBar.frame.size.height;
    [self.tabBarController.view setFrame:tabBarControllerFrame];
}

Then to reshow the tab bar when the user pops back to the top of my UINavigationController, I added this to my top view controller:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    // Hide toolbar
    [self.navigationController setToolbarHidden:YES animated:animated];
    
    // Tab bar back on to screen
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGRect tabBarControllerFrame = self.tabBarController.view.frame;
    if (tabBarControllerFrame.size.height != screenRect.size.height) {
        if (animated) {
            [UIView beginAnimations:nil context:NULL];
            [UIView setAnimationDuration:0.5];
            tabBarControllerFrame.size.height = screenRect.size.height;
            [self.tabBarController.view setFrame:tabBarControllerFrame];
            [UIView commitAnimations];
        }
        else {
            tabBarControllerFrame.size.height = screenRect.size.height;
            [self.tabBarController.view setFrame:tabBarControllerFrame];
        }
    }
}

Solution 12 - Iphone

in iOS8 it is enough to just set the hidden property of the tabBar
Like in Swift you can

rootTabVC = UITabBarController()
rootTabVC?.tabBar.hidden = true

I do this in my didFinishLaunchingWithOptions in the appdelegate and it works fine, I think if I remember correctly in the older iOS versions you also needed to set the frame of the tabBar to something outside the screen, otherwise the tabbar would not show but it will still occupy the space.

Solution 13 - Iphone

Swift and modified version of @Saurabh code

Method

func setTabBarHidden (bool:Bool){
        for view in tabBarController!.view.subviews {
            if (view.isKindOfClass(UITabBar)){
                let tabBar = view as! UITabBar
                UIView.animateWithDuration(0.3, animations: { () -> Void in
                    var offset = CGFloat(50)
                    if (bool == false){
                        offset = -50;
                    }
                    tabBar.frame = CGRect(origin: CGPointMake(tabBar.frame.origin.x, tabBar.frame.origin.y + offset), size: tabBar.frame.size)
             })   
        }
    }
}

To show

override func viewDidLoad() {
     setTabBarHidden(true)
}

To hide

override func viewWillDisappear(animated: Bool) {
    setTabBarHidden(false)
}

Solution 14 - Iphone

Updated and Working for swift 5 and ios 14.0

/*
    Shows or hides the tabbar

    :param: hidden            whether to show or hide the tabbar
    :param: animationDuration the animation's duration
*/
extension UITabBarController {
    func setHidden(hidden:Bool, animationDuration:TimeInterval = 0.25) {
        
        let screenRect = UIScreen.main.bounds
        var fHeight = screenRect.size.height
        
        if !hidden {
            fHeight -= self.tabBar.frame.size.height
        }
        
        UIView.animate(withDuration: animationDuration, animations: {
            for view in self.view.subviews {
                if view is UITabBar {
                    view.frame = CGRect(
                        x: view.frame.origin.x,
                        y: fHeight,
                        width: view.frame.size.width,
                        height: view.frame.size.height)
                }
            }
        })
    }
}

This is a more direct port (not tested):

/*
    Shows or hides the tabbar

    :param: hidden            whether to show or hide the tabbar
    :param: animationDuration the animation's duration
*/
extension UITabBarController {
    func setHidden(hidden:Bool, animationDuration:TimeInterval = 0.25) {
        
        let screenRect = UIScreen.main.bounds
        var fHeight = screenRect.size.height
        
        if UIApplication.shared.statusBarOrientation.isLandscape {
            fHeight = screenRect.size.width
        }
        
        if !hidden {
            fHeight -= self.tabBar.frame.size.height
        }
        
        UIView.animate(withDuration: animationDuration, animations: {
            for view in self.view.subviews {
                if view is UITabBar {
                    view.frame = CGRect(
                        x: view.frame.origin.x,
                        y: fHeight,
                        width: view.frame.size.width,
                        height: view.frame.size.height)
                }
                else if hidden {
                    view.frame = CGRect(
                        x: view.frame.origin.x,
                        y: view.frame.origin.y,
                        width: view.frame.size.width,
                        height: fHeight)
                }
            }
        }, completion: { finished in
            if !hidden {
                UIView.animate(withDuration: animationDuration, animations: {
                    for view in self.view.subviews {
                        if !(view is UITabBar) {
                            view.frame = CGRect(
                                x: view.frame.origin.x,
                                y: view.frame.origin.y,
                                width: view.frame.size.width,
                                height: fHeight)
                        }
                    }
                })
            }
        })
    }
}

Solution 15 - Iphone

A swift version with animation, you need set a property isHideTabBar by yourself.

self.isHideTabBar = !self.isHideTabBar
UIView.animate(withDuration: 0.5, animations: {
    self.tabBarController?.tabBar.frame = (self.tabBarController?.tabBar.frame.offsetBy(dx: 0, dy: self.isHideTabBar ? 100 : -100))!
 })

Solution 16 - Iphone

Hiding the tab bar is not an adequate solution, it won't adjust the current view controllers view height.

Instead you may simply transform the tab bar itself, either by it's height (to hide) or an identity transform to reset to visible.

extension UITabBarController {
    func setBarHiddenAnimated(_ hidden:Bool) {
        UIView.animate(withDuration: 0.3, animations: {
            if hidden {
                self.tabBar.transform = CGAffineTransform(translationX: 0, y: self.tabBar.frame.size.height)
            } else {
                self.tabBar.transform = CGAffineTransform.identity
            }
        })
    }
}

Note that you may need to set your view controller to 'extends below bottom bars' and 'extends under opaque bars' to remove the black background during animation.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionViktor ApoyanView Question on Stackoverflow
Solution 1 - IphoneSaurabhView Answer on Stackoverflow
Solution 2 - Iphonekarlbecker_comView Answer on Stackoverflow
Solution 3 - IphoneSaileshView Answer on Stackoverflow
Solution 4 - IphoneThomas VerbeekView Answer on Stackoverflow
Solution 5 - IphoneSetomidorView Answer on Stackoverflow
Solution 6 - IphoneDiegoView Answer on Stackoverflow
Solution 7 - Iphonemikemike396View Answer on Stackoverflow
Solution 8 - IphoneSifengView Answer on Stackoverflow
Solution 9 - Iphoneuser207616View Answer on Stackoverflow
Solution 10 - IphoneYevhen DubininView Answer on Stackoverflow
Solution 11 - IphoneSeanRView Answer on Stackoverflow
Solution 12 - IphoneAliView Answer on Stackoverflow
Solution 13 - IphoneHusamView Answer on Stackoverflow
Solution 14 - IphoneschmittsfnView Answer on Stackoverflow
Solution 15 - IphoneWilliam HuView Answer on Stackoverflow
Solution 16 - Iphonechris stamperView Answer on Stackoverflow