15

I'm having Three Views. I want to hide the navigation bar in the third View. Even if I give .navigationBarHidden(true) the navigation bar is displaying!

I couldn't find where I'm doing wrong. I've attached my code and the resulting screenshot below.

Xcode version - 11.1

struct ContentViewOne: View {
    var body: some View {
        NavigationView {
            ZStack {
                
                Color.yellow.edgesIgnoringSafeArea(.all)
                VStack(spacing: 20) {
                    Text("View One")
                    
                    NavigationLink(destination: ContentViewTwo()) {
                        Text("Navigate to View Two")
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.red)
                    }
                }
            }
            .navigationBarTitle("View One")
        }
    }
}

struct ContentViewTwo: View {
    var body: some View {
        
        ZStack {
            Color.green.edgesIgnoringSafeArea(.all)
            VStack(spacing: 20) {
                Text("View Two")
                NavigationLink(destination: ContentViewThree()) {
                    Text("Navigate to View Three")
                        .foregroundColor(.white)
                        .padding()
                        .background(Color.red)
                }
            }
        }
        .navigationBarTitle("View Two")
    }
}

struct ContentViewThree: View {
    var body: some View {
        ZStack {
            Color.gray.edgesIgnoringSafeArea(.all)
            Text("View Three")
        }
        .navigationBarTitle("View Three")
        .navigationBarHidden(true)
        .navigationBarBackButtonHidden(true)
    }
}

enter image description here

pkamb
  • 33,281
  • 23
  • 160
  • 191
Azhagusundaram Tamil
  • 2,053
  • 3
  • 21
  • 36

9 Answers9

42

NOTE: (For some reason it works in some cases) SwiftUI requires that you need to .navigationBarTitle for .navigationBarHidden to work properly.

NavigationView {
    ScrollView() {
     ......
    }.  
    .navigationBarTitle("") //this must be empty
    .navigationBarHidden(true)
    .navigationBarBackButtonHidden(true)
}
Rohit Makwana
  • 4,337
  • 1
  • 21
  • 29
6

I tried multiple solutions, including UINavigationControllerDelegate and nothing seems to make the navigationBar permanently hidden. Until I tried KVO :)

So if you want a permanent solution, use this:

struct NoBarNavigationView<Content: View>: View {

    private let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    var body: some View {
        NavigationView {
            content
                .introspectNavigationController { (UINavigationController) in
                    NavigationControllerDelegate.shared.becomeDelegate(of: UINavigationController)
                }
        }
    }
}

class NavigationControllerDelegate: NSObject {

    static let shared = NavigationControllerDelegate()

    func becomeDelegate(of navigationController: UINavigationController) {
        navigationController.isNavigationBarHidden = true
        navigationController.navigationBar.isHidden = true
        navigationController.navigationBar.addObserver(self, forKeyPath: "alpha", options: .new, context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        // This is necessary to ensure the UINavigationBar remains hidden
        if let navigationBar = object as? UINavigationBar {
            navigationBar.isHidden = true
        }
    }

}

Happy coding!

EDIT: As pointed out in the comments, I am using:

import Introspect

GitHub link

Miroslav Kuťák
  • 1,875
  • 1
  • 18
  • 24
4

Posting this for more visibility in dealing with SwiftUI NavigationBar not hiding, or still taking up space when it is hidden:

.navigationBarHidden(true)
.navigationBarTitle("", displayMode: .inline)
.edgesIgnoringSafeArea([.top, .bottom])

That sets a title (hack sometimes required for old swiftUI versions), hides the bar, but also tells the rendering engine to ignore any safe areas that reserve space for the navigation bar (presumptively).

smakus
  • 1,107
  • 10
  • 11
  • Line `.navigationBarTitle("", displayMode: .inline)` alone did the trick for me. It is important to set it after `.navigationBarHidden(true)` – CedricSoubrie Jan 28 '22 at 16:01
  • 1
    This was a solution for me. I don't even have a navigation view. – MGY Nov 22 '22 at 08:52
2

To hide the NavigationBar specifically in your 3rd View. You have to remove .navigationBarTitle("View Three") and the bar gets hidden:

struct ContentViewThree: View {
    var body: some View {
        ZStack {
            Color.gray.edgesIgnoringSafeArea(.all)
            Text("View Three")
        }
        .navigationBarHidden(true)
        .navigationBarBackButtonHidden(true)
    }
}
LuLuGaGa
  • 13,089
  • 6
  • 49
  • 57
2

With iOS 15.5 and 15.6 .navigationBarHidden(true) simply doesn't work. Adding .navigationBarTitle("", displayMode: .inline) doesn't help either. It's obviously a bug in iOS 15.

It's fixed in iOS 16!

Tested with Xcode 14 Simulated iOS 15.5, iPhone w/ iOS 15.6 and iOS 16 on an iPhone X, the bug got fixed in iOS 16.

Jan
  • 1,032
  • 11
  • 26
1

You need to add .navigationBarHidden(true) on navigationView, or if you have NavigationLink you need to add on the Link

   NavigationLink("",
                               destination: Text("TEST"),
                               tag: linkValue,
                               selection: $linksNavigator.selection)
                    **.navigationBarHidden(true)**
zdravko zdravkin
  • 2,090
  • 19
  • 21
  • wow, this is such a strange behaviour, to have to set navigatoinbarHidden for all the navigation links you have on the page as well – andrei Feb 15 '21 at 18:07
  • I've found this also hides the navigation bar on the view holding the navigation link (possibly this is how it works as the child view inherits the status of the parent?) – sally2000 Apr 20 '21 at 19:13
  • 1
    Unfortunately this didn't work for me :( – Rachael Sep 25 '22 at 05:59
0

Because you should add hidden properties to DetailView instead of NavigationLink,

 NavigationLink(destination: DetailView(mData: sportData)
                                .navigationBarTitle("")
                                .navigationBarHidden(true)
                                .navigationBarBackButtonHidden(true)
                
                ) {
                    Image("arrowRight3").resizable()
                    //.padding(5)
                    //.background(.red)
                       
Mucahid Uslu
  • 367
  • 3
  • 11
0

In iOS 15 you can use a @State property to toggle the state.

@State private var hideNavigationbar: Bool = false

You switching the value in .onAppear {} to true. When you dismiss the view you call .onDisappear {} and set the property to false.

Now you can use it like so:

.navigationbarHidden(hideNavigationbar)
adri567
  • 533
  • 5
  • 20
0

The latest hiding method, suitable for iOS15


.navigationBarHidden(true)
.ignoresSafeArea()


gaohomway
  • 2,132
  • 1
  • 20
  • 37