Reputation: 1952
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.
Upvotes: 15
Views: 12766
Reputation: 886
if you want dynamic navigation title you can do something like this
struct ContentView: App {
@State var selection = 1
var body: some Scene {
WindowGroup {
NavigationView {
TabView(selection: $selection) {
GridView()
.tabItem {
Label("Study", systemImage: "book")
.symbolRenderingMode(.hierarchical)
}
.tag(1)
StudyView()
.tabItem {
Label("Test", systemImage: "graduationcap")
}
.tag(2)
}
.navigationTitle(selection == 1 ? "Study a Language" : "Take a Test")
}
}
}
Also if you're getting a warning like this Trying to pop to a missing destination - SwiftUI/NavigationBridge_PhoneTV.swift:213 you can probably follow this blog https://computerlounge.it/swifui-trying-to-pop-to-missing-destination/
Upvotes: 0
Reputation: 12343
This works too in iOS 13:
var body: some View {
TabView {
NavigationView {
FirstTabbarView(viewModel: viewModel)
.navigationBarTitle("NavBar title Tabbar1", displayMode: .inline)
}
.tabItem {
Image(systemName: "house.fill")
Text("Tab bar 1")
}
NavigationView {
SecondTabbarView(viewModel: viewModel)
.navigationBarTitle("Navbar title Tabbar 2", displayMode: .inline)
}
.tabItem {
Image(systemName: "person.fill")
Text("Tab bar 2")
}
}
}
Upvotes: 0
Reputation: 7800
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.
Upvotes: 18
Reputation: 1945
If you need Login/SignUp View before tabview do not use NavigationView to wrap it. In the Login/Sign up view
@EnvironmentObject var authService:AuthService
var body: some View{
ZStack{
if(!authService.isSignedIn){
Button(action: {
self.authService.signIn()
}) {
Text("Login")
}
}
else{
TabBarView()
}
}
}
In the subviews you can control the isSignedIn variable with @EnvironmentObject
and change that value when Signed Out
This is an example of the TabBarView()
used before:
var body: some View {
TabView {
NavigationView{
FirstView()
}
.tabItem {
VStack{
Image("first")
Text("First")
}
}
NavigationView{
SecondView()
}
.tabItem {
VStack{
Image("second")
Text("Second")
}
}
}
}
This is could be one of the tabviews:
@EnvironmentObject var authService:AuthService
var body: some View {
TextView("Hello World")
.navigationBarItems(trailing: LogOutButton(logOutFunction: authService.signOut))
}
Upvotes: 2