it-swarm.com.ru

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

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

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

-(void)hideBar 
{
    self.navController.navigationBarHidden = YES;
}
-(void)showBar 
{       
    self.navController.navigationBarHidden = NO;
}
365
Lee Armstrong

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

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

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

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

1003
Alan Rogers

Другой подход, который я нашел, - установить делегат для 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 все в одном месте.

45
Chad M.

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

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

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

    [super viewWillDisappear:animated];
}
17
user486646

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

Вот так, где вам нужно это скрыть:

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

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

- (void)viewWillAppear:(BOOL)animated
{
        [yourObject showBar];
}
16
Pablo Santa Cruz

в 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)
}
14
Eugene Braginets

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

Вместо этого @Chad M.'s стратегия использования UINavigationControllerDelegate - это хороший вариант, и вот более полное решение. шаги:

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

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

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

Вот как я получил это работает.

Шаг 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 показать navBar

- (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 к изображению и сделайте navBar прозрачным.

- (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];
}
6
verma

Отдай должное ответу @ 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 контроллеров UINavigationControl в 1 StoryBoard.

4
AI Lion

В случае, если у кого-то все еще есть проблемы с ошибка быстрого обратного удаления отменена, как @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)
}

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

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

3
aunnnn

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

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

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

1
Alex

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

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

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

Навигационная панель может быть установлена ​​обратно видимой в обратном вызове ViewWillAppear ViewController.

-(void)viewWillAppear:(BOOL)animated {

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

Swift 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)
}
0
John Riselvato