Панель навігації в iPhone приховує лише на першій сторінці


381

Я маю код нижче, який приховує та показує навігаційну панель. Він прихований, коли перший погляд завантажується, а потім прихований, коли викликають "дітей". Проблема полягає в тому, що я не можу знайти подію / дію, щоб запустити її знову приховати, коли вони повернуться до кореневого виду ....

На кореневій сторінці у мене є кнопка "тест", яка виконує дії вручну, але це не дуже добре, і я хочу, щоб це було автоматичним.

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

Відповіді:


1035

Найприємніше рішення, яке я знайшов - це зробити наступне в контролері першого виду .

Ціль-С

- (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реалізацію цих методів, і відповідно до документації ви повинні викликати реалізацію супер десь у вашій реалізації .


2
Це повністю гойдає! Я боровся з цим принаймні день. Дякую!!!
Джеймс Теста

26
ПОПЕРЕДЖЕННЯ. Це створює дуже погану помилку під час швидкої зворотної роботи. Припустимо, A (без навигації) і B (з navbar) висунуті на стек. Коли ви переглядаєте B і робите швидку перемотку назад, але відпустіть достатньо рано, щоб залишитися на B, навігація все одно приховується. Тепер вже немає можливості повернутися назад. Це пов’язано з animated=YES. Я знаю, що це виглядає некрасиво animated=NO, але, здається, коли анімація для приховування навігації ще не закінчена, тоді анімація для її показу знову ігнорується. Ще немає рішення.
fabb

3
У Swift: переосмислити функцію viewWillAppear (анімоване: Bool) {self.navigationController? .SetNavigationBarHidden (правда, анімований: true) super.viewWillAppear (true)} переосмислити функцію viewWillDisappear (анімований: Bool) {self.navigationHagnageNagnagationNagnagationAntller анімований: false) super.viewWillDisappear (true)}
Кітсон

7
На запитання відповіли у 2010 році та допомагає мені наприкінці 2015 року! Дякую.
oyalhi

1
Тепер це я називаю легендарною відповіддю. Чудовий товариш трюків Навіть працюючи після десятиліть ... Реалізував те саме швидко, працюючи бездоганно. +1 для вашої відповіді @Alan Rogers
onCompletion

62

Ще один підхід, який я знайшов, - це встановити делегата для 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в одному місці.


Коли це назве?
Zalak Patel

1
Ідеальне рішення. Це має бути прийнятою відповіддю. Дякую!
Сама

Ідеальна відповідь. Він також працює в тому випадку, якщо ми не зможемо замінити методи viewWillAppear та viewWillDisappear на першому контролері перегляду.
pjuzeliunas

1
Дивовижно. Обрана відповідь працює нормально, однак лише у простих додатках. Ця відповідь спрацьовує, коли навігаційна панель знаходиться в контролері вкладок і різними способами штовхає / представляє різні КК.
Джонатан Вінгер-Ланг

Це найкраща відповідь. У верхній відповіді може виникнути помилка, як опис @ fabb .
Ryan.Yuen

18

Один незначний твік, який я мав зробити на інші відповіді, - це лише приховати смужку в viewWillDisappear, якщо причина її зникнення пов'язана з тим, що навігаційний елемент натискається на нього. Це тому, що погляд може зникнути з інших причин.

Тож я лише приховую смугу, якщо цей вид більше не є верхнім видом:

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

    [super viewWillDisappear:animated];
}

3
+1, зазвичай ви не бажаєте показувати панель навігації під час натискання модального діалогового вікна.
Жоао Портела

17

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

На кшталт цього, де вам потрібно сховати це:

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

Ось так, де вам потрібно це показати:

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

Лі, якщо це вирішило вашу проблему, позначте Пабло як відповідь "рішення".
Рог

2
Єдина проблема з цим полягає в тому, що навігаційна панель «вискакує» та переглядається під час переходу від одного виду до іншого. Чи можливо просто мати навігаційну панель не на першому огляді, а коли другий вигляд ковзає на місці, у неї є панель навігації, без жодного спливу?
Хеннінг

2
@henning Щоб зробити NavBar слайд вхід / вихід так, як ви очікували, вам потрібно використовувати setNavigationBarHidden: animated :. Дивіться відповідь Алана Роджерса нижче (який дійсно слід позначати як "рішення").
Нік Форж

2
Ця відповідь трохи неправильна (viewWill / DidAppear) повинна викликати супер. Також дивіться мою відповідь нижче щодо рішення, де не потрібно додавати його до КОЖНОГО контролера перегляду.
Алан Роджерс

15

На даний момент прийнята відповідь не відповідає наміченій поведінці, описаній у питанні. Питання вимагає, щоб панель навігації була прихована на кореневому контролері перегляду, але видима скрізь, але прийнята відповідь приховує панель навігації на певному контролері перегляду. Що відбувається, коли інший екземпляр першого контролера перегляду висувається на стек? Він приховає панель навігації, навіть якщо ми не дивимось на контролер кореневого виду.

Натомість, стратегія використання @Chad M. 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];
    }
}

2
Це більш відповідна відповідь, ніж прийнята
Павло Гуров

14

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

Ви могли б пояснити, чому ви перевіряєте! = себе?
Кітсон

2
@Kitson, перевіри відповідь користувача486646: Один незначний
Євген Брагінець

Здається, що якщо ви користуєтесь цим, navcontroller.navagationBarHiddenвін зламає весь навігаційний контролер (не просувайте вперед і назад). Щоб змусити його працювати, я використовував navigationController?.navigationBar.hiddenзамість цього. Переміщення все ще працює, і воно не залишає порожнього місця, оскільки воно, здається, знаходиться в стек-огляді чи щось таке
Sirens

8

Подякуйте на відповідь @ 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 StoryBoard.


Подумайте, це найчистіша відповідь. Спасибі
DaSilva

6

Після декількох випробувань тут я зрозумів, як я працював над тим, що хотів. Це те, що я намагався. - У мене є вид із зображенням. і мені хотілося, щоб зображення перейшло на весь екран. - У мене теж є навігаційний контролер з 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];
}

4

У випадку, якщо хтось все-таки відчуває проблеми зі швидкою заднім числом, скасовується помилка, як @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 показано) мають різні стилі рядка стану (наприклад, темний і світлий). Щойно ви запустите зворотній шар, щоб вивести контролер перегляду, з'явиться додаткова кольорова анімація в рядку стану. Якщо ви відпустите палець, щоб скасувати інтерактивний поп, анімація в рядку стану не закінчена , навігаційна панель назавжди зникла!

Однак ця помилка не виникає, якщо стилі рядка стану обох контролерів перегляду однакові.


1

Якщо ви хочете повністю приховати панель навігації в контролері, набагато чистішим рішенням є в кореневому контролері щось подібне:

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

Якщо натиснути на дочірній вигляд у контролері, панель навігації залишиться прихованою; якщо ви хочете відобразити його просто у дитини, ви додасте код для відображення it(self.navigationController.navigationBarHidden=NO;)у viewWillAppearзворотному дзвінку та аналогічно код для його приховуванняviewWillDisappear


0

Найпростіша реалізація може полягати в тому, щоб кожен контролер перегляду вказував, чи прихована його панель навігації у своєму viewWillAppear:animated:методі Цей же підхід добре працює і для приховування / показу панелі інструментів:

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

Насправді, моя пропозиція має сенс лише для панелі інструментів, оскільки приховування панелі навігації без відповідного виклику показує, що це не дозволить користувачам повернутися назад із поточного подання.
SteveCaine

0

Приховування панелі навігації лише на першій сторінці можна досягти і за допомогою раскадровки. На інформаційній дошці перейдіть на сторінку Сцена навігаційного контролера-> Навігаційна панель . І виберіть властивість " Прихований " у інспектора "Атрибути" . Це дозволить приховати панель навігації, починаючи з першого контролера перегляду, поки не стане видимим для потрібного контролера перегляду.

Панель навігації може бути повернута до видимого в зворотному виклику ViewController ViewWillAppear.

-(void)viewWillAppear:(BOOL)animated {

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

0

Швидкий 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)
}

-1

Реалізуючи цей код у своєму 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];
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.