When using hidesBottomBarWhenPushed, i want the tab bar to reappear when i push another view
Asked Answered
P

6

12

I have a navigation controller. For one of the views i want to hide the bottom tab bar, so it gets the max possible screen real estate. To do this, i have:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.hidesBottomBarWhenPushed = YES; // To hide the tab bar
    }
    return self;
}

But for the next view that i push on the stack, i want the tab bar to reappear. Is there a way to do this?

Pathfinder answered 24/5, 2011 at 22:36 Comment(0)
R
4

One can make it reappear but it will result in an incorrect animation. Page comes in left and the bottom bar right. So it is probably not the behavior you want. But in the same controller, do self.hidesBottomBarWhenPushed = NO; before pushing the next view controller in.

River answered 25/5, 2011 at 1:8 Comment(1)
That does actually work, however it means that the bottom bar slides in from the left while the newly pushed view slides in from the right - it looks very bewildering. So another option would be good. Maybe i need to set its frame?Pathfinder
J
13

As of iOS5, there's a very easy means of accomplishing this. It's essentially the same method as Deepak, but there aren't any artifacts with the animation - everything looks as expected.

On init, set

self.hidesBottomBarWhenPushed = YES;

just as you have above. When it's time to push the new controller on the stack, it's as simple as:

self.hidesBottomBarWhenPushed = NO;

UIViewController *controller = [[[BBListingController alloc] init] autorelease];
[self.navigationController pushViewController:controller];

self.hidesBottomBarWhenPushed = YES;

It's important to reset the value to YES after the controller has been pushed in order to re-hide the bar when the user taps the Back button and the view comes back into view.

Joycejoycelin answered 10/5, 2012 at 17:53 Comment(1)
This works, but the problem is if controller pushes another controller, it will have the bottom bar hidden.Sansom
G
10

I'm have solved this problem like that:

Almost all my ViewControllers are children of BaseViewController.

So, example:

class BaseVC: UIViewController {
    final override var hidesBottomBarWhenPushed: Bool {
        get {
            if navigationController?.viewControllers.last == self {
                return prefersBottomBarHidden ?? super.hidesBottomBarWhenPushed
            } else {
                return false
            }
        } set {
            super.hidesBottomBarWhenPushed = newValue
        }
   }
   private(set) var prefersBottomBarHidden: Bool?
}

Just override variable "prefersBottomBarHidden" in ViewController where BottomBar should be hidden:

override var prefersBottomBarHidden: Bool? { return true }
Greenquist answered 15/10, 2017 at 14:14 Comment(3)
This should be the accepted solution. It works well when pushing and popping a combination of controllers that want or don't want the bottom bar hidden. Thanks!Sansom
This seems to be the only reliable solution - especially if you use a proper code architecture that does not push other VCs from within a VC. Would be nicer if it was a protocol since I want to avoid to declare all my VCs as a subclass of a base VC, but since we need to override the hidesBottomBarWhenPushed a protocol is not possible. Now if only that would also resolve the issue regarding SplitViewController I'd be super happy :) => openradar.appspot.com/24846972Leguminous
@Leguminous did you find a solution for the SplitViewController yet?Edinburgh
M
5

It's been a while since this question was asked, but none of these answers address using Storyboard segues. It turns out to be pretty easy:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "MyViewControllerIdentifier" {

        // Hide the tabbar during this segue
        hidesBottomBarWhenPushed = true

        // Restore the tabbar when it's popped in the future
        DispatchQueue.main.async { self.hidesBottomBarWhenPushed = false }

    }
}
Miltonmilty answered 3/1, 2018 at 4:9 Comment(0)
R
4

One can make it reappear but it will result in an incorrect animation. Page comes in left and the bottom bar right. So it is probably not the behavior you want. But in the same controller, do self.hidesBottomBarWhenPushed = NO; before pushing the next view controller in.

River answered 25/5, 2011 at 1:8 Comment(1)
That does actually work, however it means that the bottom bar slides in from the left while the newly pushed view slides in from the right - it looks very bewildering. So another option would be good. Maybe i need to set its frame?Pathfinder
I
4

Case one: To hide UITabbarController in a cetain UIVIewController, for example while calling self.performSegueWithIdentifier("Identifier", sender: self), it is necesssary prior to to that, set self.hidesBottomBarWhenPushed = true flag. And after self.hidesBottomBarWhenPushed = false flag. But we have to understad that through one UIViewController, UITabbarController will re-appear and, in case if you need to use UITabbarController with single UIViewControler, it wont yield right result.

in the FirstItemViewController

    @IBAction func pushToControllerAction(sender: AnyObject) {
        self.hidesBottomBarWhenPushed = true
        self.performSegueWithIdentifier("nextController", sender: self)
        self.hidesBottomBarWhenPushed = false
    }

enter image description here

Case Two: To hide UITabbarController in a certain UIVIewController, after which a UITabbarController should be popped, it is necessary, for example, while calling self.performSegueWithIdentifier("nextController", sender: self) , to set self.hidesBottomBarWhenPushed = true before the method. Alse willMoveToParentViewController(parent: UIViewController?) in the method should be configured as it shown in the code example.

in the first UIViewController "FirstItemViewController"

 @IBAction func pushToControllerAction(sender: AnyObject) {
     self.hidesBottomBarWhenPushed = true
     self.performSegueWithIdentifier("nextController", sender: self)
 }

in the next UIViewController "ExampleViewController"`

 override func willMoveToParentViewController(parent: UIViewController?) {
         if parent == nil {
             var viewControllers = self.navigationController!.viewControllers
             if ((viewControllers[viewControllers.count - 2]).isKindOfClass(FirstItemViewController.self)) {
                 (viewControllers[viewControllers.count - 2] as! FirstItemViewController).hidesBottomBarWhenPushed = false
             }
         }
 }

Swift 3 code:

let viewControllers = self.navigationController!.viewControllers
                if ((viewControllers[viewControllers.count - 2]) is (FirstItemViewController)) {
                    (viewControllers[viewControllers.count - 2] as! FirstItemViewController).hidesBottomBarWhenPushed = false
                }

enter image description here

Test project

Informal answered 22/3, 2016 at 7:4 Comment(0)
C
1

In a root view controller "A" (which is showing the tabBar), when it comes time to show another view controller "B" where no tabBar is wanted:

self.hidesBottomBarWhenPushed = YES; // hide the tabBar when pushing B
[self.navigationController pushViewController:viewController_B animated:YES];
self.hidesBottomBarWhenPushed = NO; // for when coming Back to A

In view controller B, when it comes time to show a third view controller C (tabBar wanted again):

self.hidesBottomBarWhenPushed = NO; // show the tabbar when pushing C
[self.navigationController pushViewController:viewController_C animated:YES];
self.hidesBottomBarWhenPushed = YES; // for when coming Back to B
Cobb answered 7/2, 2013 at 5:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.