iPhone chỉ ẩn Thanh điều hướng trên trang đầu tiên


381

Tôi có mã dưới đây ẩn và hiển thị thanh điều hướng. Nó bị ẩn khi chế độ xem đầu tiên tải và sau đó bị ẩn khi "trẻ em" được gọi. Rắc rối là tôi không thể tìm thấy sự kiện / hành động để kích hoạt nó để ẩn lần nữa khi họ quay lại chế độ xem gốc ....

Tôi có một nút "kiểm tra" trên trang gốc thực hiện hành động theo cách thủ công nhưng nó không đẹp và tôi muốn nó tự động.

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

Câu trả lời:


1035

Giải pháp tốt nhất tôi đã tìm thấy là thực hiện các thao tác sau trong trình điều khiển xem đầu tiên .

Mục tiêu-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];
}

Nhanh

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

Điều này sẽ khiến thanh điều hướng hoạt động từ bên trái (cùng với chế độ xem tiếp theo) khi bạn đẩy tiếp theo UIViewControllertrên ngăn xếp và di chuyển sang bên trái (cùng với chế độ xem cũ), khi bạn nhấn nút quay lại trên UINavigationBar.

Cũng xin lưu ý rằng đây không phải là các phương thức ủy nhiệm, bạn đang ghi đè UIViewControllerviệc triển khai các phương thức này và theo tài liệu bạn phải gọi triển khai của siêu nhân ở đâu đó trong quá trình triển khai của bạn .


2
Đây hoàn toàn là đá! Tôi đã phải vật lộn với điều này trong ít nhất một ngày. Cảm ơn!!!
James Testa

26
CẢNH BÁO: Điều này tạo ra một lỗi rất xấu khi thực hiện backswipe nhanh. Giả sử A (không có thanh điều hướng) và B (có thanh điều hướng) được đẩy lên ngăn xếp. Khi xem B và thực hiện backswipe nhanh, nhưng giải phóng đủ sớm để ở lại B, thanh điều hướng vẫn bị ẩn. Bây giờ không còn cách nào để quay lại nữa. Điều này là do animated=YES. Tôi biết nó trông xấu xí animated=NO, nhưng dường như khi hoạt hình để ẩn thanh điều hướng vẫn chưa kết thúc, thì hoạt hình để hiển thị lại bị bỏ qua. Chưa có giải pháp nào.
fabb

3
Trong Swift: ghi đè chế độ xem funcWillAppear (hoạt hình: Bool) {self.navlationControll? .IsetNavlationBarHidden (true, hoạt hình: true) super.viewWillAppear (true)} ghi đè func viewWillDisappear (hoạt hình: Bool) {self.avav hoạt hình: sai) super.viewWillDisappear (đúng)}
Kitson

7
Câu hỏi đã được trả lời vào năm 2010 và giúp tôi vào cuối năm 2015! Cảm ơn bạn.
oyaltyhi 8/12/2015

1
Bây giờ đó là những gì tôi gọi là một câu trả lời huyền thoại. Người bạn đời tuyệt vời. Ngay cả làm việc sau nhiều thập kỷ ... Thực hiện tương tự trong nhanh chóng, làm việc hoàn hảo. +1 cho câu trả lời của bạn @Alan Rogers
onCompletion

62

Một cách tiếp cận khác mà tôi tìm thấy là thiết lập một đại biểu cho NavigationController:

navigationController.delegate = self;

và sử dụng setNavigationBarHiddentrongnavigationController: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];
}

Cách dễ dàng để tùy chỉnh hành vi cho ViewControllertất cả mọi người ở một nơi.


Khi nào điều này sẽ được gọi?
Zalak Patel

1
Giải pháp hoàn hảo. Đây phải là câu trả lời được chấp nhận. Cảm ơn!
Samah

Câu trả lời hoàn hảo. Nó cũng hoạt động trong trường hợp chúng ta không thể ghi đè các phương thức viewWillAppear và viewWillDisappear trên trình điều khiển khung nhìn đầu tiên.
pjuzeliunas

1
Tuyệt vời. Câu trả lời được chọn hoạt động tốt, tuy nhiên chỉ trong các ứng dụng đơn giản. Câu trả lời này hoạt động khi thanh điều hướng nằm trong bộ điều khiển tab và đẩy / trình bày các VC khác nhau theo nhiều cách khác nhau.
Jonathan Winger-Lang

Đây là câu trả lời tốt nhất. Câu trả lời hàng đầu có thể xảy ra lỗi như mô tả của @ fabb .
Ryan.Yuen

18

Một điều chỉnh nhỏ mà tôi phải thực hiện đối với các câu trả lời khác là chỉ bỏ ẩn thanh trong viewWillDisappear nếu lý do nó biến mất là do một mục điều hướng bị đẩy vào nó. Điều này là do chế độ xem có thể biến mất vì những lý do khác.

Vì vậy, tôi chỉ bỏ ẩn thanh nếu chế độ xem này không còn là chế độ xem trên cùng:

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

    [super viewWillDisappear:animated];
}

3
+1, bạn thường không muốn hiển thị thanh điều hướng khi đẩy hộp thoại phương thức.
João Portela

17

Tôi sẽ đặt mã trong đại biểu viewWillAppear cho mỗi chế độ xem được hiển thị:

Giống như nơi này bạn cần ẩn nó:

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

Như thế này, nơi bạn cần hiển thị nó:

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

Lee, nếu điều này khắc phục vấn đề của bạn, hãy đánh dấu Pablo là câu trả lời "giải pháp".
Rog

2
Vấn đề duy nhất với điều này là thanh điều hướng "bật" ra và vào chế độ xem khi bạn điều hướng từ chế độ xem này sang chế độ xem tiếp theo. Có thể chỉ có thanh điều hướng không có ở chế độ xem đầu tiên và khi chế độ xem thứ hai trượt vào vị trí, nó có thanh điều hướng mà không có bất kỳ cửa sổ bật lên nào không?
Henning

2
@henning Để thực hiện trượt vào / ra NavBar như bạn mong đợi, bạn cần sử dụng setNavlationBarHidden: hoạt hình :. Xem câu trả lời của Alan Rogers bên dưới (cần được đánh dấu là "giải pháp").
Nick Forge

2
Câu trả lời này hơi sai (viewWill / DidAppear) nên gọi siêu. Ngoài ra Xem câu trả lời của tôi dưới đây để biết giải pháp mà bạn không cần thêm nó vào MỌI trình điều khiển chế độ xem.
Alan Rogers

15

Câu trả lời hiện được chấp nhận không phù hợp với hành vi dự định được mô tả trong câu hỏi. Câu hỏi yêu cầu thanh điều hướng bị ẩn trên bộ điều khiển xem gốc, nhưng có thể nhìn thấy ở mọi nơi khác, nhưng câu trả lời được chấp nhận sẽ ẩn thanh điều hướng trên một bộ điều khiển xem cụ thể. Điều gì xảy ra khi một phiên bản khác của trình điều khiển khung nhìn đầu tiên được đẩy lên ngăn xếp? Nó sẽ ẩn thanh điều hướng mặc dù chúng ta không nhìn vào bộ điều khiển xem gốc.

Thay vào đó, chiến lược sử dụng của @Chad M. UINavigationControllerDelegatelà một giải pháp tốt và đây là một giải pháp hoàn thiện hơn. Các bước:

  1. Phân lớp UINavigationController
  2. Thực hiện -navigationController:willShowViewController:animatedphương thức hiển thị hoặc ẩn thanh điều hướng dựa trên việc nó có hiển thị trình điều khiển xem gốc hay không
  3. Ghi đè các phương thức khởi tạo để đặt lớp con UINavestionControll làm đại biểu của chính nó

Mã hoàn chỉnh cho giải pháp này có thể được tìm thấy trong Gist này . Đây là cách navigationController:willShowViewController:animatedthực hiện:

- (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
Đây là một câu trả lời phù hợp hơn câu trả lời được chấp nhận
Pavel Gurov

14

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

bạn có thể giải thích lý do tại sao bạn kiểm tra! = self?
Kitson

2
@Kitson, kiểm tra câu trả lời của người dùng486646: Một điều chỉnh nhỏ tôi phải thực hiện đối với các câu trả lời khác là chỉ bỏ ẩn thanh trong viewWillDisappear nếu lý do nó biến mất là do một mục điều hướng bị đẩy vào nó. Điều này là do chế độ xem có thể biến mất vì những lý do khác. Vì vậy, tôi chỉ bỏ ẩn thanh nếu chế độ xem này không còn là chế độ xem cao nhất
Eugene Braginets

Có vẻ như nếu bạn sử dụng navcontroller.navagationBarHiddennó sẽ phá vỡ toàn bộ bộ điều khiển điều hướng (không vuốt qua lại). Để làm cho nó hoạt động tôi sử dụng navigationController?.navigationBar.hiddenthay thế. Thao tác vuốt vẫn hoạt động và nó không để lại khoảng trống vì dường như nó nằm trong stackview hoặc thứ gì đó
Sirens

8

Cung cấp tín dụng của tôi cho câu trả lời của @ chad-m.

Đây là phiên bản Swift:

  1. Tạo một tập tin mới 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. Đặt lớp của UINavestionContaptor của bạn trong StoryBoard thành MyNavlationControll Đó là nó!MyNavestionControll

Sự khác biệt giữa câu trả lời của chad-m và của tôi:

  1. Kế thừa từ UINavestionContaptor, vì vậy bạn sẽ không làm ô nhiễm rootViewControll của mình.

  2. sử dụng self.viewControllers.firstchứ không phải homeViewController, vì vậy bạn sẽ không làm điều này 100 lần cho 100 UINavestionControllers của bạn trong 1 StoryBoard.


Hãy nghĩ rằng đây là câu trả lời sạch nhất. Cảm ơn
DaSilva

6

Sau nhiều thử nghiệm ở đây là cách tôi làm cho nó hoạt động cho những gì tôi muốn. Đây là những gì tôi đã cố gắng. - Tôi có một cái nhìn với một hình ảnh. và tôi muốn có hình ảnh ở chế độ toàn màn hình. - Tôi cũng có bộ điều khiển điều hướng với tabBar. Vì vậy, tôi cần phải che giấu điều đó quá. - Ngoài ra, yêu cầu chính của tôi không chỉ là che giấu, mà còn có hiệu ứng mờ dần trong khi hiển thị và ẩn.

Đây là cách tôi làm cho nó hoạt động.

Bước 1 - Tôi có một hình ảnh và người dùng chạm vào hình ảnh đó một lần. Tôi chụp cử chỉ đó và đẩy nó vào cái mới imageViewController, trong đó imageViewController, tôi muốn có hình ảnh toàn màn hình.

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

Bước 2 - Tất cả các bước dưới đây đều có trong ImageViewControll

Bước 2.1 - Trong ViewDidLoad, hiển thị navBar

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

Bước 2.2 - Vào viewDidAppear, thiết lập tác vụ hẹn giờ với độ trễ (Tôi đã đặt nó cho độ trễ 1 giây). Và sau khi trì hoãn, thêm hiệu ứng mờ dần. Tôi đang sử dụng alpha để sử dụng fading.

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

Bước 2.3 - Dưới viewWillAppear, thêm cử chỉ SingleTap vào hình ảnh và làm mờ 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];
 }

Bước 3 - Cuối cùng viewWillDisappear, đảm bảo đặt lại tất cả mọi thứ

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

Trong trường hợp bất cứ ai vẫn gặp sự cố với lỗi hủy backswipe nhanh như @fabb đã nhận xét trong câu trả lời được chấp nhận.

Tôi quản lý để khắc phục điều này bằng cách ghi đè viewDidLayoutSubviews, ngoài ra viewWillAppear/viewWillDisappearnhư dưới đây:

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

Trong trường hợp của tôi, tôi nhận thấy rằng đó là do bộ điều khiển xem gốc (nơi điều hướng bị ẩn) và bộ điều khiển xem đẩy (điều hướng được hiển thị) có các kiểu thanh trạng thái khác nhau (ví dụ: tối và sáng). Thời điểm bạn bắt đầu backswipe để bật trình điều khiển xem, sẽ có thêm hình ảnh động thanh trạng thái. Nếu bạn thả ngón tay ra để hủy pop tương tác, trong khi hoạt hình trên thanh trạng thái chưa kết thúc , thanh điều hướng sẽ không còn nữa!

Tuy nhiên, lỗi này không xảy ra nếu kiểu thanh trạng thái của cả hai bộ điều khiển xem giống nhau.


1

Nếu điều bạn muốn là ẩn hoàn toàn thanh điều hướng trong bộ điều khiển, thì một giải pháp sạch hơn nhiều là, trong bộ điều khiển gốc, có một cái gì đó như:

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

Khi bạn đẩy chế độ xem con trong bộ điều khiển, Thanh điều hướng sẽ bị ẩn; nếu bạn muốn hiển thị nó ngay ở trẻ, bạn sẽ thêm mã để hiển thị it(self.navigationController.navigationBarHidden=NO;)trong cuộc viewWillAppeargọi lại, và tương tự mã để ẩn nó trênviewWillDisappear


0

Việc thực hiện đơn giản nhất có thể là chỉ cần mỗi bộ điều khiển khung nhìn xác định xem thanh điều hướng của nó có bị ẩn hay không trong viewWillAppear:animated:phương thức của nó . Cách tiếp cận tương tự cũng hoạt động tốt để ẩn / hiển thị thanh công cụ:

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

Trên thực tế, đề xuất của tôi chỉ có ý nghĩa đối với thanh công cụ, vì việc ẩn thanh điều hướng mà không có cuộc gọi phù hợp để hiển thị nó sẽ khiến người dùng không thể điều hướng trở lại từ chế độ xem hiện tại.
SteveCaine

0

Chỉ ẩn thanh điều hướng trên trang đầu tiên cũng có thể đạt được thông qua bảng phân cảnh. Trên bảng phân cảnh, goto Điều khiển điều hướng Cảnh-> Thanh điều hướng . Và chọn thuộc tính ' Ẩn ' từ thanh tra Thuộc tính . Điều này sẽ ẩn thanh điều hướng bắt đầu từ trình điều khiển khung nhìn đầu tiên cho đến khi nó hiển thị cho trình điều khiển khung nhìn được yêu cầu.

Thanh điều hướng có thể được đặt lại để hiển thị trong cuộc gọi lại ViewWillAppear của ViewContoder.

-(void)viewWillAppear:(BOOL)animated {

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

0

Swift 4:

Trong trình điều khiển xem bạn muốn ẩn thanh điều hướng khỏi.

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

Bằng cách triển khai mã này trong ViewContoder của bạn, bạn có thể nhận được hiệu ứng này Trên thực tế, mẹo là, ẩn điều hướngBar khi Trình điều khiển đó được khởi chạy

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

và bỏ ẩn thanh điều hướng khi người dùng rời khỏi trang đó làm điều này là viewWillDisappear

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    [super viewWillDisappear:animated];
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.