iPhone은 첫 페이지에서만 탐색 모음을 숨 깁니다.


381

탐색 표시 줄을 숨기고 표시하는 코드가 아래에 있습니다. 첫 번째 뷰가로드되면 숨겨지고 "자식"이 호출 될 때 숨겨집니다. 문제는 루트보기로 돌아갈 때 다시 숨기도록 트리거하는 이벤트 / 작업을 찾을 수 없다는 것입니다.

루트 페이지에 수동으로 작업을 수행하는 "테스트"버튼이 있지만 예쁘지 않고 자동으로 작동하기를 원합니다.

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

답변:


1035

내가 찾은 가장 좋은 해결책은 첫 번째 뷰 컨트롤러 에서 다음을 수행하는 것 입니다.

목표 -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의 구현을 호출해야합니다 .


2
이것은 완전히 흔들린다! 나는 적어도 하루 동안 이것으로 고투하고 있었다. 감사!!!
James Testa

26
경고 : 빠른 뒤로 밀기 작업을 수행하면 매우 나쁜 버그가 발생합니다. 스택에 A (탐색기 없음) 및 B (탐색기 있음)가 밀렸다 고 가정합니다. 보기 B에서 빠른 뒤로 스 와이프를 수행하지만 B를 유지하기에 충분히 일찍 릴리스하면 탐색 표시 줄이 여전히 숨겨집니다. 이제 더 이상 돌아갈 방법이 없습니다. 이 때문 animated=YES입니다. 나는 못 생겼다는 것을 알고 animated=NO있지만 탐색 표시 줄을 숨기는 애니메이션이 아직 완료되지 않은 경우 다시 표시하는 애니메이션이 무시됩니다. 아직 해결책이 없습니다.
fabb

3
Swift에서 : func viewWillAppear (애니메이션 : Bool) {self.navigationController? .setNavigationBarHidden (true, animated : true) super.viewWillAppear (true)} func viewWillDisappear (animated : Bool) {self.navigationController? .setNavigationBarHidden (false, animated : false) super.viewWillDisappear (true)}
Kitson

7
질문은 2010 년에 답변되었으며 2015 년 말에 나를 도와줍니다! 감사합니다.
oyalhi

1
이것이 바로 전설적인 답변입니다. 최고의 트릭 메이트. 수십 년이 지난 후에도 ... 빠른 일을 신속하게 구현했습니다. 귀하의 답변에 +1 @Alan Rogers
onCompletion

62

내가 찾은 또 다른 접근법은 다음에 대한 대리자를 설정하는 것입니다 NavigationController.

navigationController.delegate = self;

및 사용 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];
}

ViewController한 곳에서 각각의 동작을 쉽게 사용자 지정할 수 있습니다 .


언제 전화할까요?
Zalak Patel

1
완벽한 솔루션. 이것이 정답입니다. 감사!
Samah

완벽한 답변. 첫 번째 뷰 컨트롤러에서 viewWillAppear 및 viewWillDisappear 메서드를 재정의 할 수없는 경우에도 작동합니다.
pjuzeliunas

1
대박. 선택한 답변은 괜찮지 만 간단한 앱에서만 작동합니다. 이 답변은 탐색 모음이 탭 컨트롤러에 있고 다양한 VC를 다양한 방식으로 푸시 / 표시 할 때 작동합니다.
Jonathan Winger-Lang

이것이 가장 좋은 대답입니다. 최고 답변은 @ 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, 일반적으로 모달 대화 상자를 누를 때 탐색 모음을 표시하고 싶지 않습니다.
João Portela

17

표시되는 각 뷰 의 viewWillAppear 델리게이트에 코드를 추가합니다 .

숨길 필요가있는 곳에서 이렇게 :

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

이것을 보여줘야 할 곳과 같이 :

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

이 문제가 해결 되었으면 Pablo의 답변을 "솔루션"으로 표시하십시오.
Rog

2
이 문제의 유일한 문제점은 한보기에서 다음보기로 탐색 할 때 탐색 표시 줄이 "튀어 나와서보기"입니다. 첫 번째보기에 탐색 막대가없는 것이 가능하고 두 번째보기가 제자리로 슬라이드되면 탐색 표시 줄이 팝업없이 나타납니다.
Henning

2
@henning NavBar 슬라이드를 예상 한대로 삽입 / 출력하려면 setNavigationBarHidden : animated :를 사용해야합니다. 아래의 Alan Rogers의 답변을 참조하십시오 (실제로는 "솔루션"으로 표시되어야 함).
Nick Forge

2
이 답변은 약간 잘못되었습니다 (viewWill / DidAppear) super 호출해야합니다. 또한 모든 뷰 컨트롤러에 추가 할 필요가없는 솔루션에 대해서는 아래 답변을 참조하십시오.
Alan Rogers

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

스위프트 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)
}

왜 당신이! = 자기를 확인하는지 설명 할 수 있습니까?
Kitson

2
@Kitson, user486646 '답변 을 확인하십시오. 다른 답변에 대한 약간의 조정은 viewWillDisappear에서 막대를 숨기기 취소하는 것입니다. 다른 이유로보기가 사라질 수 있기 때문입니다. 난 단지 바 숨기기를 취소 그래서이보기는 더 이상 최상위보기없는 경우
유진 Braginets

당신이 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. StoryBoard에서 UINavigationController의 클래스를 MyNavigationController로 설정하십시오 .MyNavigationController

chad-m의 답변과 내 차이점의 차이점 :

  1. UINavigationController에서 상속되므로 rootViewController를 오염시키지 않습니다.

  2. 사용 self.viewControllers.first하기보다는 homeViewController당신이 1 스토리 보드에 100 UINavigationControllers이 100 번을하지 않도록.


이것이 가장 깨끗한 대답이라고 생각하십시오. 감사합니다
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

스토리 보드를 통해서도 첫 페이지에만 탐색 표시 줄을 숨길 수 있습니다. 스토리 보드에서 Navigation Controller Scene-> Navigation Bar로 이동하십시오 . 그리고 속성 관리자 에서 ' 숨겨진 '속성을 선택하십시오 . 필요한 viewcontroller에 표시 될 때까지 첫 번째 viewcontroller에서 시작하는 탐색 막대가 숨겨집니다.

탐색 막대는 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 에서이 코드를 구현하면이 효과를 얻을 수 있습니다. 실제로 트릭은 컨트롤러가 시작될 때 navigationBar를 숨 깁니다.

- (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];
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.