iPhone скрывает Панель навигации только на первой странице

StackOverflow https://stackoverflow.com/questions/845583

Вопрос

У меня есть приведенный ниже код, который скрывает и показывает панель навигации.Он скрывается при загрузке первого представления, а затем скрывается при вызове "дочерних элементов".Проблема в том, что я не могу найти событие / действие, чтобы заставить его снова скрыться, когда они вернутся к корневому представлению....

У меня есть кнопка "проверить" на корневой странице, которая вручную выполняет действие, но это некрасиво, и я хочу, чтобы это было автоматически.

-(void)hideBar 
{
    self.navController.navigationBarHidden = YES;
}
-(void)showBar 
{       
    self.navController.navigationBarHidden = NO;
}
Это было полезно?

Решение

Самое приятное решение, которое я нашел, - это сделать следующее в контроллер первого вида.

Цель-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];
}

Быстрый

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

Это приведет к тому, что панель навигации будет анимироваться слева (вместе со следующим видом), когда вы нажмете на следующий UIViewController в стеке и переместите анимацию влево (вместе со старым видом), когда вы нажмете кнопку "Назад" на UINavigationBar.

Пожалуйста, обратите также внимание, что это не методы делегирования, вы переопределяете UIViewControllerреализации этих методов, и в соответствии с документацией вы должен вызвать реализацию super где-то в вашей реализации.

Другие советы

Другой подход, который я нашел, заключается в том, чтобы установить делегат для NavigationController:

navigationController.delegate = self;

и использовать setNavigationBarHidden в 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];
}

Простой способ настроить поведение для каждого ViewController все в одном месте.

Одна небольшая настройка, которую мне пришлось внести в другие ответы, заключается в том, чтобы отображать панель в viewWillDisappear только в том случае, если причина ее исчезновения связана с нажатием на нее элемента навигации.Это связано с тем, что представление может исчезнуть по другим причинам.

Поэтому я показываю панель только в том случае, если этот вид больше не является самым верхним видом:

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

    [super viewWillDisappear:animated];
}

Я бы поместил код в Просмотр появится делегировать на каждом показываемом представлении:

Вот так, где тебе нужно это спрятать:

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

Вот так, где вам нужно это показать:

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

в 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)
}

Принятый в настоящее время ответ не соответствует предполагаемому поведению, описанному в вопросе.Вопрос требует, чтобы панель навигации была скрыта на корневом контроллере представления, но видна везде, но принятый ответ скрывает панель навигации на определенном контроллере представления.Что происходит, когда другой экземпляр первого контроллера представления помещается в стек?Это скроет панель навигации, даже если мы не смотрим на корневой контроллер представления.

Вместо этого, @Chad M.'s СТРАТЕГИИ об использовании UINavigationControllerDelegate это хороший вариант, и вот более полное решение.Шаги:

  1. Подкласс UINavigationController
  2. Внедрить -navigationController:willShowViewController:animated способ отображения или скрытия панели навигации в зависимости от того, отображается ли на ней корневой контроллер представления
  3. Переопределите методы инициализации, чтобы установить подкласс UINavigationController в качестве собственного делегата

Полный код для этого решения можно найти в эта Суть.Вот этот 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];
    }
}

После нескольких проб вот как я заставил его работать на то, что я хотел.Это то, что я пытался сделать.- У меня есть представление с изображением.и я хотел, чтобы изображение было на весь экран.- У меня тоже есть навигационный контроллер с панелью вкладок.Так что мне тоже нужно это скрыть.- Кроме того, моим главным требованием было не просто скрывать, но и создавать эффект затухания при показе и скрытии.

Вот как у меня это получилось.

Шаг 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];
} 

Шаг 2 - Все эти шаги ниже приведены в ImageViewController

Шаг 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];
}

Шаг 2.2 - В viewDidAppear, настройте задачу таймера с задержкой (у меня она установлена на задержку в 1 секунду).А после задержки добавьте эффект затухания.Я использую альфа-версию для использования затухания.

- (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.
}

шаг 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];
 }

Шаг 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];
}

Отдайте должное ответу @chad-m.

Вот версия 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. Установите для вашего класса UINavigationController в StoryBoard значение MyNavigationController MyNavigationController Вот и все!

Разница между ответом чада-м и моим:

  1. Наследуется от UINavigationController, так что вы не будете загрязнять свой RootViewController.

  2. использование self.viewControllers.first вместо того , чтобы homeViewController, так что вы не будете делать это 100 раз для ваших 100 UINavigationControllers в 1 раскадровке.

На случай, если у кого-то все еще возникли проблемы с быстрая обратная прокладка отменена ошибка как прокомментировал @fabb в принятом ответе.

Мне удается исправить это, переопределив 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)
}

В моем случае я замечаю, что это происходит из-за корневого контроллера представления (где nav скрыт) и толкаемого контроллера представления (отображается nav). имеет разные стили строки состояния (например,темный и светлый).В тот момент, когда вы запустите backswipe, чтобы открыть контроллер просмотра, появится дополнительная цветовая анимация строки состояния.Если вы отпустите палец, чтобы отменить интерактивное всплывающее, пока анимация строки состояния не завершена, панель навигации исчезла навсегда!

Однако эта ошибка не возникает, если стили строки состояния обоих контроллеров представления одинаковы.

Если вы хотите полностью скрыть панель навигации в контроллере, гораздо более чистым решением будет иметь в корневом контроллере что-то вроде:

@implementation MainViewController
- (void)viewDidLoad {
    self.navigationController.navigationBarHidden=YES;
    //...extra code on view load  
}

Когда вы нажимаете дочерний вид в контроллере, панель навигации остается скрытой;если вы хотите отобразить его только в дочернем элементе, вы добавите код для отображения it(self.navigationController.navigationBarHidden=NO;) в viewWillAppear обратный вызов, и аналогично код для скрытия его на viewWillDisappear

Простейшей реализацией может быть просто указание каждому контроллеру представления, скрыта ли его панель навигации в его viewWillAppear:animated: способ.Тот же подход хорошо работает и для скрытия / отображения панели инструментов:

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

Скрытие панели навигации только на первой странице также может быть достигнуто с помощью раскадровки.На раскадровке, гото Сцена навигационного контроллера-> Панель навигации.И выберите 'Скрытый" собственность из Инспектор атрибутов.Это скроет панель навигации, начиная с первого viewcontroller, до тех пор, пока она не станет видимой для требуемого viewcontroller.

Панель навигации может быть возвращена в видимое состояние при обратном вызове viewWillAppear ViewController.

-(void)viewWillAppear:(BOOL)animated {

    [self.navigationController setNavigationBarHidden:YES animated:animated];
    [super viewWillAppear:animated];                                                  
}

Быстрый 4:

В контроллере представления, от которого вы хотите скрыть панель навигации.

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

Внедрив этот код в свой ViewController, вы можете получить этот эффект На самом деле хитрость в том, чтобы скрыть панель навигации при запуске этого контроллера

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

и отображать панель навигации, когда пользователь покидает эту страницу, это viewWillDisappear

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    [super viewWillDisappear:animated];
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top