ios iPhone仅在第一页隐藏导航栏

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/845583/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:54:54  来源:igfitidea点击:

iPhone hide Navigation Bar only on first page

iosuinavigationcontrollerhide

提问by Lee Armstrong

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

回答by Alan Rogers

The nicest solution I have found is to do the following in the first view controller.

我找到的最好的解决方案是在第一个视图控制器中执行以下操作。

Objective-C

目标-C

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:YES animated:animated];
    [super viewWillAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:animated];
    [super viewWillDisappear:animated];
}

Swift

迅速

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

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

This will cause the navigation bar to animate in from the left (together with the next view) when you push the next UIViewControlleron the stack, and animate away to the left (together with the old view), when you press the back button on the UINavigationBar.

当您将下一个推入UIViewController堆栈时,这将导致导航栏从左侧(与下一个视图一起)动画,当您按下堆栈上的后退按钮时,将动画移到左侧(与旧视图一起)UINavigationBar.

Please note also that these are not delegate methods, you are overriding UIViewController's implementation of these methods, and according to the documentation you must call the super's implementation somewhere in your implementation.

另请注意,这些不是委托方法,您正在覆盖UIViewController这些方法的实现,并且根据文档,您必须在实现中的某处调用 super 的实现

回答by Chad M.

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

我发现的另一种方法是为 设置一个委托NavigationController

navigationController.delegate = self;

and use setNavigationBarHiddenin navigationController:willShowViewController:animated:

并使用setNavigationBarHiddennavigationController: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 ViewControllerall in one place.

ViewController在一个地方为每个人定制行为的简单方法。

回答by Chad M.

One slight tweak I had to make on the other answers is to only unhide the bar in viewWillDisappear if the reason it is disappearing is due to a navigation item being pushed on it. This is because the view can disappear for other reasons.

我必须对其他答案进行的一个小调整是,只有在 viewWillDisappear 中的栏消失的原因是由于导航项被推到它上面时才取消隐藏它。这是因为视图可能因其他原因而消失。

So I only unhide the bar if this view is no longer the topmost view:

因此,如果此视图不再是最顶层的视图,我只会取消隐藏栏:

- (void) viewWillDisappear:(BOOL)animated
{
    if (self.navigationController.topViewController != self)
    {
        [self.navigationController setNavigationBarHidden:NO animated:animated];
    }

    [super viewWillDisappear:animated];
}

回答by Pablo Santa Cruz

I would put the code in the viewWillAppeardelegate on each view being shown:

我会将代码放在正在显示的每个视图的viewWillAppear委托中:

Like this where you need to hide it:

像这样你需要隐藏它的地方:

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject hideBar];
}

Like this where you need to show it:

像这样你需要展示它的地方:

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject showBar];
}

回答by hunteros

The currently accepted answer does not match the intended behavior described in the question. The question asks for the navigation bar to be hidden on the root view controller, but visible everywhere else, but the accepted answer hides the navigation bar on a particular view controller. What happens when another instance of the first view controller is pushed onto the stack? It will hide the navigation bar even though we are not looking at the root view controller.

当前接受的答案与问题中描述的预期行为不符。该问题要求导航栏隐藏在根视图控制器上,但在其他任何地方都可见,但接受的答案隐藏了特定视图控制器上的导航栏。当第一个视图控制器的另一个实例被推入堆栈时会发生什么?即使我们没有查看根视图控制器,它也会隐藏导航栏。

Instead, @Chad M.'s strategyof using the UINavigationControllerDelegateis a good one, and here is a more complete solution. Steps:

相反,@Chad M. 的使用策略UINavigationControllerDelegate是一个很好的策略,这里有一个更完整的解决方案。脚步:

  1. Subclass UINavigationController
  2. Implement the -navigationController:willShowViewController:animatedmethod to show or hide the navigation bar based on whether it is showing the root view controller
  3. Override the initialization methods to set the UINavigationController subclass as its own delegate
  1. 子类 UINavigationController
  2. 实现-navigationController:willShowViewController:animated根据是否显示根视图控制器来显示或隐藏导航栏的方法
  3. 覆盖初始化方法以将 UINavigationController 子类设置为其自己的委托

Complete code for this solution can be found in this Gist. Here's the navigationController:willShowViewController:animatedimplementation:

这个解决方案的完整代码可以在这个 Gist 中找到。这是navigationController:willShowViewController:animated实现:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    /* Hide navigation bar if root controller */
    if ([viewController isEqual:[self.viewControllers firstObject]]) {
        [self setNavigationBarHidden:YES animated:animated];
    } else {
        [self setNavigationBarHidden:NO animated:animated];
    }
}

回答by Eugene Braginets

in Swift 3:

在 Swift 3 中:

override func viewWillAppear(_ animated: Bool) {
    navigationController?.navigationBar.isHidden = true
    super.viewWillAppear(animated)
}


override func viewWillDisappear(_ animated: Bool) {
    if (navigationController?.topViewController != self) {
        navigationController?.navigationBar.isHidden = false
    }
    super.viewWillDisappear(animated)
}

回答by AI Lion

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

感谢@chad-m 的回答。

Here is the Swift version:

这是 Swift 版本:

  1. Create a new file MyNavigationController.swift
  1. 创建一个新文件 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 MyNavigationControllerThat's it!
  1. 将 StoryBoard 中 UINavigationController 的类设置为 MyNavigationController 就是这样!我的导航控制器

Difference between chad-m's answer and mine:

chad-m 的答案和我的答案之间的区别:

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

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

  1. 继承自UINavigationController,所以不会污染你的rootViewController。

  2. 使用self.viewControllers.first而不是homeViewController,因此您不会为 1 个 StoryBoard 中的 100 个 UINavigationController 执行 100 次此操作。

回答by verma

After multiple trials here is how I got it working for what I wanted. This is what I was trying. - I have a view with a image. and I wanted to have the image go full screen. - I have a navigation controller with a tabBar too. So i need to hide that too. - Also, my main requirement was not just hiding, but having a fading effect too while showing and hiding.

经过多次试验,我是如何让它按照我想要的方式工作的。这就是我正在尝试的。- 我有一个图像视图。我想让图像全屏显示。- 我也有一个带有 tabBar 的导航控制器。所以我也需要隐藏它。- 另外,我的主要要求不仅是隐藏,而且在显示和隐藏时也有褪色效果。

This is how I got it working.

这就是我让它工作的方式。

Step 1 - I have a image and user taps on that image once. I capture that gesture and push it into the new imageViewController, its in the imageViewController, I want to have full screen image.

第 1 步 - 我有一个图像,用户点击该图像一次。我捕捉到那个手势并将其推入新的imageViewController,它在imageViewController,我想要全屏图像。

- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer {  
NSLog(@"Single tap");
ImageViewController *imageViewController =
[[ImageViewController alloc] initWithNibName:@"ImageViewController" bundle:nil];

godImageViewController.imgName  = // pass the image.
godImageViewController.hidesBottomBarWhenPushed=YES;// This is important to note. 

[self.navigationController pushViewController:godImageViewController animated:YES];
// If I remove the line below, then I get this error. [CALayer retain]: message sent to deallocated instance . 
// [godImageViewController release];
} 

Step 2 - All these steps below are in the ImageViewController

第 2 步 - 以下所有这些步骤都在 ImageViewController 中

Step 2.1 - In ViewDidLoad, show the navBar

步骤 2.1 - 在 ViewDidLoad 中,显示导航栏

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(@"viewDidLoad");
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}

Step 2.2 - In viewDidAppear, set up a timer task with delay ( I have it set for 1 sec delay). And after the delay, add fading effect. I am using alpha to use fading.

步骤 2.2 - 在 中viewDidAppear,设置一个带延迟的计时器任务(我将它设置为 1 秒延迟)。并在延迟后,添加淡入淡出效果。我正在使用 alpha 来使用淡入淡出。

- (void)viewDidAppear:(BOOL)animated
{
NSLog(@"viewDidAppear");

myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self     selector:@selector(fadeScreen) userInfo:nil repeats:NO];
}

- (void)fadeScreen
{
[UIView beginAnimations:nil context:nil]; // begins animation block
[UIView setAnimationDuration:1.95];        // sets animation duration
self.navigationController.navigationBar.alpha = 0.0;       // Fades the alpha channel of   this view to "0.0" over the animationDuration of "0.75" seconds
[UIView commitAnimations];   // commits the animation block.  This Block is done.
}

step 2.3 - Under viewWillAppear, add singleTap gesture to the image and make the navBar translucent.

步骤 2.3 - 在 下viewWillAppear,向图像添加 singleTap 手势并使导航栏半透明。

- (void) viewWillAppear:(BOOL)animated
{

NSLog(@"viewWillAppear");


NSString *path = [[NSBundle mainBundle] pathForResource:self.imgName ofType:@"png"];

UIImage *theImage = [UIImage imageWithContentsOfFile:path];

self.imgView.image = theImage;

// add tap gestures 
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];  
[self.imgView addGestureRecognizer:singleTap];  
[singleTap release];  

// to make the image go full screen
self.navigationController.navigationBar.translucent=YES;
}

- (void)handleTap:(UIGestureRecognizer *)gestureRecognizer 
{ 
 NSLog(@"Handle Single tap");
 [self finishedFading];
  // fade again. You can choose to skip this can add a bool, if you want to fade again when user taps again. 
 myTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self  selector:@selector(fadeScreen) userInfo:nil repeats:NO];
 }

Step 3 - Finally in viewWillDisappear, make sure to put all the stuff back

第 3 步 - 最后viewWillDisappear,确保将所有东西放回原处

- (void)viewWillDisappear: (BOOL)animated 
{ 
self.hidesBottomBarWhenPushed = NO; 
self.navigationController.navigationBar.translucent=NO;

if (self.navigationController.topViewController != self)
{
    [self.navigationController setNavigationBarHidden:NO animated:animated];
}

[super viewWillDisappear:animated];
}

回答by aunnnn

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

万一有人仍然遇到快速后退的问题,取消了@fabb 在接受的答案中评论的错误

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

viewDidLayoutSubviews除了viewWillAppear/viewWillDisappear如下所示,我设法通过覆盖来解决这个问题:

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.

但是,如果两个视图控制器的状态栏样式相同,则不会发生此错误。

回答by Alex

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 viewWillAppearcallback, and similarly the code for hiding it on viewWillDisappear

当您在控制器中推送子视图时,导航栏将保持隐藏;如果你只想在孩子中显示它,你将添加it(self.navigationController.navigationBarHidden=NO;)viewWillAppear回调中显示的代码,以及类似的隐藏它的代码viewWillDisappear