NavigationView title doesn't appear when the views are in TabView in SwiftUI

Osama Naeem picture Osama Naeem · Aug 2, 2019 · Viewed 7.9k times · Source

I have two Views and each of them contains NavigationView with title. I have created a TabBar View which also has a NavigationView on it.

struct TabbarView: View {
var body: some View {
    NavigationView{
    TabView {
        MainContentView()
            .tabItem {
                VStack {
                    Text("Main")
                }
        }.tag(0)

        SearchContentView()
            .tabItem {
                VStack {
                    Text("Search")
                }
        }.tag(1)
    }
    }.navigationBarBackButtonHidden(true)
    .navigationBarHidden(true)
}

}

I have tried hiding the navigationBar for this view but that doesn't work. Only the navigation bar of this view appears.

This is MainContentView()

struct MainContentView: View {

var body: some View {
    NavigationView {
        Text("Some Content View")
        }
    .navigationBarTitle("Travel")
}

}

Any idea how to go about this. Thanks!

Update: Basically when I tap on a Log In Button, I am passing TabBarView() through NavigationLink.

   NavigationLink(destination: TabbarView()) {
                        HStack {
                            Text("Log In")
                        }
                        .padding()
                        .frame(width: geometry.size.width - 40, height: 40)
                        .foregroundColor(Color.white)
                        .background(Color.blue)
                        .cornerRadius(5)
                }.padding(.bottom, 40)

In doing that, it shows the TabbarView() with child views this is what I see: The space above "Travel" (navigationBarTitle of the childView) is the navigationBar of the tabbar since I am pushing it into navigationStack.

enter image description here

Answer

graycampbell picture graycampbell · Aug 2, 2019

The first thing to point out here is that all of the navigation bar modifiers you have in your code should be modifiers on a view inside of the NavigationView, not modifiers on NavigationView itself. From the documentation for .navigationBarTitle, for example:

This modifier only takes effect when this view is inside of and visible within a NavigationView.

Also, there is no need to have a NavigationView wrapping your TabView and then another inside your MainContentView. This will only lead to nested navigation bars, and you definitely don't want that. Instead, just use one NavigationView. I would also suggest that you not put the NavigationView inside the MainContentView body.

I've refactored your code to show what I'm talking about, although I wasn't sure where you were trying to use .navigationBarBackButtonHidden and .navigationBarHidden, so I omitted them. Just keep in mind that they function just like .navigationBarTitle - you need to use them as modifiers on a view inside NavigationView, not on NavigationView itself.

struct TabBarView: View {
    var body: some View {
        TabView {
            NavigationView {
                MainContentView()
            }
                .tag(0)
                .tabItem {
                    Text("Main")
                }

            SearchContentView()
                .tag(1)
                .tabItem {
                    Text("Search")
                }
        }
    }
}
struct MainContentView: View {
    var body: some View {
        Text("Some Content View")
            .navigationBarTitle("Travel")
    }
}

As you might notice, I also removed the VStack from .tabItem. You can put both Text and Image inside .tabItem without the need for a VStack, and if I'm not mistaken, .tabItem ignores anything that is not Text or Image anyway.