I am developing an app in Swift with SwiftUI.
I have this setup where I put a TabView inside a NavigationView and used the navigationBarTitle on the tabView. I did this because if I put the NavigationView inside the TabView, I cannot make the Tab bar disappear when I go to a NavigationLink: it seems currently impossible with swiftUI.
The current problem with my setup is that since I put the .navigationBarTitle on the TabView, the title does not change when I change the tab view and I cannot reset the .navigationBarTitle on the subview for some reason.
Here is a code to explain what I am saying:
ContentView :
NavigationView {
TabView {
SomeSubView().tabItem() { Text("SomeSubView") }
Text("dummy2").tabItem() { Text("dummy2") }
Text("dummy3").tabItem() { Text("dummy3") }
}.navigationBarTitle("hello")
}
SomeSubView:
List(somearray) { element in
NavigationLink(destination: elementDetails()) {
SomeRowView()
}
}
Here is a preview (the code above isn't exactly my code but just an example):
Now I woukd like to put the .navigationBarTitle inside the SomeSubView() like this:
List(somearray) { element in
NavigationLink(destination: elementDetails()) {
SomeRowView()
}
}.navigationBarTitle("title2")
Instead of choosing a global title for the TabView. So in that case I would have something like:
NavigationView {
TabView {
SomeSubView().tabItem() { Text("SomeSubView") }
}
}
Then I choose a .navigationBarTitle inside the SomeSubView() but it doesn't work (the title bar just does not appear, instead the tab title is changed and that's not what I want).
So I finally came up with this kind of setup:
@State private var title = Text("Default_Title")
var body: some View {
NavigationView {
TabView {
SomeSubView().tabItem { Text("SomeSubView") }.onAppear { self.title = Text("new_title") }
Text("dummy2").tabItem { Text("dummy2") }
Text("dummy3").tabItem { Text("dummy3") }
}.navigationBarTitle(title)
}
}
This way, I can dynamically change the title when I click on a tab view and it works fine but I also need to set different .navigationBarItems for each tab view so I did the same thing for the leading and trailing parameters of .navigationBarItems, like this:
@State private var title = Text("Default_Title")
@State private var leading = NavBar_leading(type: "FirstView")
@State private var trailing = NavBar_trailing(type: "FirstView")
var body: some View {
NavigationView {
TabView {
SomeSubView().tabItem { Text("SomeSubView") }.onAppear {
self.title = Text("new_title")
self.leading = NavBar_leading(type: "FirstView")
self.trailing = NavBar_trailing(type: "FirstView")
}
Text("dummy2").tabItem { Text("dummy2") }
Text("dummy3").tabItem { Text("dummy3") }
}.navigationBarTitle(title).navigationBarItems(leading: leading, trailing: trailing)
}
}
As you can see, I dynamically update the leading and trailing parameters of .navigationBarItems to set different items (buttons in my case) for each tab view. The NavBar_leading and NavBar_trailing view return a Button text type depending on the parameter I passed, like this:
struct NavBar_leading: View {
var type: String
var body: some View {
if type == "FirstView" {
return Button(action: {
print("hello1 empty")
}) {
Text("")
}
} else if (type == "SecondView") {
return Button(action: {
print("hello2")
}) {
Text("SomeButton")
}
} else {
return Button(action: {
print("hello3 empty")
}) {
Text("")
}
}
}
}
Now the problem is that I want to return sometimes a Button Text, but sometimes a Button Image from the same NavBar_leading view but Swift does not allow me to have different types returned from the same view. I thought the Button view was one type but it seems that depending on what you put inside, it becomes another type.
I heard that the Any view type isn't a good practice in Swift and has performance impact, so I'm looking for a way to achieve what I want here.
I explained everything because I am open to any other suggestion, like if I can do something totally better I am open to restart from scratch, so here are my questions:
- Is my handling with the TabView inside the NavigationView a good idea for what I needed to do? Is there something better that I do not know?
- Is there any other way to display a different title for each tab view instead of a global title that I update like I did?
- Is there any way to return different Button types from a view without using an Any view type? Anything better that I can do?
Thank you