iPhone hide Navigation Bar only on first page

2019-01-02 16:03发布

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;
}

14条回答
何处买醉
2楼-- · 2019-01-02 16:56

Give my credit to @chad-m 's answer.

Here is the Swift version:

  1. Create a new file MyNavigationController.swift

import UIKit

class MyNavigationController: UINavigationController, UINavigationControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.delegate = self
    }

    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        if viewController == self.viewControllers.first {
            self.setNavigationBarHidden(true, animated: animated)
        } else {
            self.setNavigationBarHidden(false, animated: animated)
        }
    }

}
  1. Set your UINavigationController's class in StoryBoard to MyNavigationController MyNavigationController That's it!

Difference between chad-m's answer and mine:

  1. Inherit from UINavigationController, so you won't pollute your rootViewController.

  2. use self.viewControllers.first rather than homeViewController, so you won't do this 100 times for your 100 UINavigationControllers in 1 StoryBoard.

查看更多
查无此人
3楼-- · 2019-01-02 16:57

Another approach I found is to set a delegate for the NavigationController:

navigationController.delegate = self;

and use setNavigationBarHidden in navigationController:willShowViewController:animated:

- (void)navigationController:(UINavigationController *)navigationController 
      willShowViewController:(UIViewController *)viewController 
                    animated:(BOOL)animated 
{   
    // Hide the nav bar if going home.
    BOOL hide = viewController != homeViewController;
    [navigationController setNavigationBarHidden:hide animated:animated];
}

Easy way to customize the behavior for each ViewController all in one place.

查看更多
只靠听说
4楼-- · 2019-01-02 16:57

In case anyone still having trouble with the fast backswipe cancelled bug as @fabb commented in the accepted answer.

I manage to fix this by overriding viewDidLayoutSubviews, in addition to viewWillAppear/viewWillDisappear as shown below:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.setNavigationBarHidden(false, animated: animated)
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    self.navigationController?.setNavigationBarHidden(true, animated: animated)
}

//*** This is required to fix navigation bar forever disappear on fast backswipe bug.
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.navigationController?.setNavigationBarHidden(false, animated: false)
}

In my case, I notice that it is because the root view controller (where nav is hidden) and the pushed view controller (nav is shown) has different status bar styles (e.g. dark and light). The moment you start the backswipe to pop the view controller, there will be additional status bar colour animation. If you release your finger in order to cancel the interactive pop, while the status bar animation is not finished, the navigation bar is forever gone!

However, this bug doesn't occur if status bar styles of both view controllers are the same.

查看更多
人气声优
5楼-- · 2019-01-02 16:59

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:

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setToolbarHidden:YES/NO animated:animated];
    [super viewWillAppear:animated];
}
查看更多
栀子花@的思念
6楼-- · 2019-01-02 17:00

Hiding navigation bar only on first page can be achieved through storyboard as well. On storyboard, goto Navigation Controller Scene->Navigation Bar. And select 'Hidden' property from the Attributes inspector. This will hide navigation bar starting from first viewcontroller until its made visible for the required viewcontroller.

Navigation bar can be set back to visible in ViewController's ViewWillAppear callback.

-(void)viewWillAppear:(BOOL)animated {

    [self.navigationController setNavigationBarHidden:YES animated:animated];
    [super viewWillAppear:animated];                                                  
}
查看更多
看风景的人
7楼-- · 2019-01-02 17:06

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:

@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

查看更多
登录 后发表回答