50

Is there a way to hide tabbar and remove that space left (around 50px) ?

I tried

self.tabBarController?.tabBar.hidden = true
self.extendedLayoutIncludesOpaqueBars = true

No luck. I see blank space.

Utku Dalmaz
  • 9,780
  • 28
  • 90
  • 130

15 Answers15

77

If you're still seeing a black stripe under your hidden tab bar, have you tried to select Extend Edges Under Opaque Bars here?

enter image description here

Make also sure that Under Bottom Bars is still selected. Hope it helps!

Smnd
  • 1,579
  • 11
  • 7
40

Swift 3:

extension UITabBarController {
    func setTabBarVisible(visible:Bool, duration: TimeInterval, animated:Bool) {
        if (tabBarIsVisible() == visible) { return }
        let frame = self.tabBar.frame
        let height = frame.size.height
        let offsetY = (visible ? -height : height)

        // animation
        UIViewPropertyAnimator(duration: duration, curve: .linear) {
            self.tabBar.frame.offsetBy(dx:0, dy:offsetY)
            self.view.frame = CGRect(x:0,y:0,width: self.view.frame.width, height: self.view.frame.height + offsetY)
            self.view.setNeedsDisplay()
            self.view.layoutIfNeeded()
        }.startAnimation()
    }

    func tabBarIsVisible() ->Bool {
        return self.tabBar.frame.origin.y < UIScreen.main.bounds.height
    }
}

To use (if for example self is a UITabBarController):

self.setTabBarVisible(visible: false, duration: 0.3, animated: true)

Swift 2.x:

extension UITabBarController {
    func setTabBarVisible(visible:Bool, duration: NSTimeInterval, animated:Bool) {
        if (tabBarIsVisible() == visible) { return }
        let frame = self.tabBar.frame
        let height = frame.size.height
        let offsetY = (visible ? -height : height)

        // animation
        UIView.animateWithDuration(animated ? duration : 0.0) {
            self.tabBar.frame = CGRectOffset(frame, 0, offsetY)
            self.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height + offsetY)
            self.view.setNeedsDisplay()
            self.view.layoutIfNeeded()
        }
    }

    func tabBarIsVisible() ->Bool {
        return self.tabBar.frame.origin.y < UIScreen.mainScreen().bounds.height
    }
}

To use:

self.tabBarController?.setTabBarVisible(visible: false, duration: 0.3, animated: true)
Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
  • 1
    There is a black bar is visible when tab bar disappears and re-appears between screens. How can I hide it? – serdar aylanc Feb 27 '17 at 19:44
  • 2
    I used this approach (very similar code) with reliable performance up until iOS 10. I'm now having a lot of issues with this code in iOS 11 (Xcode 9 beta 6). The bottom of the view is getting drawn off screen and the tab bar gets offset incorrectly from bottom of screen when returning to the view controller from another view controller. Is anyone else having issues with this code in iOS 11? Have you found a fix / alternate approach? – Justin Domnitz Aug 25 '17 at 20:17
  • @Justin Domnitz I've update my code. About your issue I've test it and it happened only with Xcode 9 and simulators, not with a real device. If you puts some breakpoints during the animation you can see all values (frames and heights..) are correct. – Alessandro Ornano Aug 26 '17 at 09:38
  • 2
    @AlessandroOrnano Thanks for taking a look. I'm seeing issues with physical devices as well. My view controller hierarchy is very complex though. Tab view controller with split view controller with page view controller with container views, etc. Having lots of issues with this approach now on both simulator and physical dives. I'm pulling it out where and replacing it with alternative approaches where possible. :( – Justin Domnitz Aug 28 '17 at 13:45
  • 1
    @JustinDomnitz I've had this problem too and it turned out to be caused by the blue "Personal Hotspost" bar on top of the screen. Instead of comparing the tabBar to `UIScreen.mainScreen().bounds.height` I changed it to `view.bounds.height` and now it's working fine. – dbmrq Sep 10 '17 at 21:12
  • Yeah this doesn't work if you're showing the uitabbarcontroller within a container view that doesn't take up the whole screen. If you don't have the tab bar disappearing under any other circumstances, you can remove the code that checks if it is visible or not. Otherwise you'll need to hard-code some computations that include knowledge of the other subview heights, or put in a call to another part of your app that knows total view states (I.E. hidden or not hidden tab bar) – TheJeff Jun 23 '19 at 19:40
33

After saw your screenshot in comment. I think you can try to set hidesBottomBarWhenPushed to true.

hidesBottomBarWhenPushed = true

Or storyboard.

enter image description here

It will hide bottom bar automatically when you pushed to another view controller, and appear it again when you go back.

JZAU
  • 3,550
  • 31
  • 37
  • This is definitely the best, works out of the box without having to add anything in the viewWillAppear/Disappear methods. Never noticed before that property was there! – fray88 Aug 05 '16 at 09:34
  • Perfect! This is absolutely the most right solution imo! – Nicolai Harbo Oct 10 '17 at 13:58
22

Programmatically, add this to the next view controller for swift 4.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    tabBarController?.tabBar.isHidden = true
    edgesForExtendedLayout = UIRectEdge.bottom
    extendedLayoutIncludesOpaqueBars = true
}

And add a background color

5

NOTE - This solution is to just to remove white space left after hiding tab bar.

For hiding tab bar best solution is - @Michael Campsall answer here

The simplest solution to this is to change your view's(in my case its tableView) bottom constraints, instead of giving bottom constraints with BottomLayoutGuide give it with superview. Screenshots attached for reference.

Constraints shown in below screenshots creates the problem, change it according to next screenshot.

Change constraints shown in this screenshot according to below screenshot

Actual constraints to remove white space should be according to this(below) screenshot.

enter image description here

Community
  • 1
  • 1
Ajay Kumar
  • 1,807
  • 18
  • 27
4

For those that like to do everything programmatically, add this line to the init method of a ViewController that shouldn't have the tabBar:

hidesBottomBarWhenPushed = true
budiDino
  • 13,044
  • 8
  • 95
  • 91
4

I was facing the same issue and root cause was BOTTOM CONSTRAINT

Make sure you set the bottom constraint of your bottom most view in the main view hierarchy with SUPERVIEW, NOT "SAFE AREA"

Hope this helps someone..

Dhaval H. Nena
  • 3,992
  • 1
  • 37
  • 50
3

The third answer on this question works for me in the following way:

The code on my view controller

@IBAction func buttonPressed(sender: AnyObject) {

    setTabBarVisible(!tabBarIsVisible(), animated: true)

}

func setTabBarVisible(visible: Bool, animated: Bool) {
    // hide tab bar
    let frame = self.tabBarController?.tabBar.frame
    let height = frame?.size.height
    var offsetY = (visible ? -height! : height)
    print ("offsetY = \(offsetY)")

    // zero duration means no animation
    let duration:NSTimeInterval = (animated ? 0.3 : 0.0)

    // animate tabBar
    if frame != nil {
        UIView.animateWithDuration(duration) {
            self.tabBarController?.tabBar.frame = CGRectOffset(frame!, 0, offsetY!)
            self.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height + offsetY!)
            self.view.setNeedsDisplay()
            self.view.layoutIfNeeded()
            return
        }
    }
}



func tabBarIsVisible() -> Bool {
    return self.tabBarController?.tabBar.frame.origin.y < UIScreen.mainScreen().bounds.height
}

In storyboard:

The view controller main view background color is black color: enter image description here

Then you could have another view inside (background color white), constrained trailing and leading space to superview and top and bottom space to the layout guide.

enter image description here

And the result is:

enter image description here

Community
  • 1
  • 1
valencieu
  • 178
  • 1
  • 12
  • check this screenshot please, http://s32.postimg.org/hbvmdbop1/IMG_2931.jpg, as you can see there is still black space – Utku Dalmaz May 09 '16 at 06:14
3

My preferred way to do that is using a wrapping controller. If I want to hide the tab bar, I just increase the height of the tab bar controller, thus effectively the tab bar is moved out of the screen.

With this solution you don't need to hack tab bar frame and you don't depend on navigation controller push animation:

import UIKit

class ViewController: UIViewController {
    let tabController: UITabBarController = {
        let tabController = UITabBarController()
        // setup your tabbar controller here

        return tabController;
    }()

    var tabbarHidden = false {
        didSet {
            var frame = self.view.bounds;

            if (tabbarHidden) {
                frame.size.height += self.tabController.tabBar.bounds.size.height;
            }

            self.tabController.view.frame = frame;
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // add the tab controller as child controller
        addChildViewController(self.tabController)
        self.tabController.view.frame = self.view.bounds
        self.tabController.view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
        self.view.addSubview(self.tabController.view)
        self.tabController.didMoveToParentViewController(self)

        // for debugging
        let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(switchTabbar))
        self.tabController.view.addGestureRecognizer(tapRecognizer)
    }

    override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return self.tabController
    }

    override func childViewControllerForStatusBarHidden() -> UIViewController? {
        return self.tabController
    }

    func switchTabbar() {
        UIView.animateWithDuration(0.3) {
            self.tabbarHidden = !self.tabbarHidden
        }
    }
}

enter image description here

Sulthan
  • 128,090
  • 22
  • 218
  • 270
2

try to set the tab bar translucent to before you hide the tab bar set to false again when you want to show again.

it works for me.

tabBarController?.tabBar.isTranslucent = true
Faiz
  • 91
  • 1
  • 5
2

Tested in Swift 5.4.

If you're adding any ViewController's view as subview programmatically and not using pushViewController, then you can simply try as follows:

// When you wanna hide TabBar
tabBarController?.tabBar.isHidden = true
tabBarController?.tabBar.isTranslucent = true // This is the key point!
// When you wanna show TabBar
tabBarController?.tabBar.isHidden = false
tabBarController?.tabBar.isTranslucent = false // This is the key point!
RoyRao
  • 161
  • 8
1

Yes. You can hide your tab bar when you push to view controller. You can show tab bar in your home. You can hide your tab bar when you push to next View controller.

See the Hide Botton Bar on Push following image and set in all viewcontrollers where you dont want tab bar.

enter image description here

Hope it helps..

Balaji Ramakrishnan
  • 1,909
  • 11
  • 22
1

Sometimes that easiest way is just to add a view that uses the UIScreen bounds.

let whiteView = UIView()
    whiteView.backgroundColor = .white
    view.addSubview(whiteView)
    whiteView.translatesAutoresizingMaskIntoConstraints = false
    whiteView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    whiteView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    whiteView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    whiteView.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height).isActive = true

Cause sometimes the view edges extends beyond the nav bar giving you new problems if you extend the view layout.

0

This code works on iOS 10, 11, and iPhone X (including simulators) to show/hide the tabBar. I created it several years (iOS 7 time frame?) and it has worked reliably since that time.

It works great on iPhone X as long as content content in your childViewControllers (in tabs) is pinned to topLayoutGuide, bottomLayoutGuide or SafeArea and not the main views walls. Then it all just works. Enjoy!

@interface UITabBarController (HideTabBar)
@property (nonatomic, getter=isTabBarHidden) BOOL tabBarHidden;
-(void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated;
@end

@implementation UITabBarController (HideTabBar)
-(BOOL)isTabBarHidden
{
    CGRect viewFrame = self.view.frame;
    CGRect tabBarFrame = self.tabBar.frame;
    return tabBarFrame.origin.y >= viewFrame.size.height;
}

-(void)setTabBarHidden:(BOOL)hidden
{
    [self setTabBarHidden:hidden animated:NO];
}

-(void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated
{
    BOOL isHidden = self.tabBarHidden;    
    if(hidden == isHidden)return;

    UIView *transitionView = [[[self.view.subviews reverseObjectEnumerator] allObjects] lastObject];
    if(transitionView == nil) {
        NSLog(@"UITabBarCategory can't get the container view");
        return;
    }    
    CGRect viewFrame = self.view.bounds;
    CGRect tabBarFrame = self.tabBar.frame;
    CGRect containerFrame = transitionView.frame;
    CGRect selectedVCFrame = containerFrame;

    tabBarFrame.origin.y = viewFrame.size.height - (hidden ? 0 : tabBarFrame.size.height);
    containerFrame.size.height = viewFrame.size.height - (hidden ? 0 : tabBarFrame.size.height);
    if([self.moreNavigationController.viewControllers containsObject:self.selectedViewController]) {
        selectedVCFrame = self.selectedViewController.view.frame;
        selectedVCFrame.size.height += hidden ? tabBarFrame.size.height : -tabBarFrame.size.height;
    }
    self.selectedViewController.view.frame = selectedVCFrame;

    [UIView animateWithDuration:.5 animations:^{
        self.tabBar.frame = tabBarFrame;
        transitionView.frame = containerFrame;
        [self.selectedViewController.view setNeedsLayout];
    }];
}
@end

Usage - I call it in the viewController on rotation events like so:

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

    // Hide TabBar on iPhone, iPod Touch
    if([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad) {
        if(_startDateEditor.editing) return;
        if(fromInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown || fromInterfaceOrientation == UIInterfaceOrientationPortrait)
            [self.tabBarController setTabBarHidden:YES animated:YES];
        else
            [self.tabBarController setTabBarHidden:NO animated:YES];
    }
}
Cliff Ribaudo
  • 8,932
  • 2
  • 55
  • 78
0

For me in iOS 13 I had to display image in cell with full screen, I had collection view with trailing, leading, top, bottom constraint. I removed all constraint. set collection view frame to UIScreen.main.bounds. then return sizeForItemAt as collection frame size.

alitosuner
  • 984
  • 1
  • 10
  • 15