Assuming we have a SwiftUI view containing
struct ContentView: View {
var body: some View {
TabView {
FirstView().tabItem {
// tabItem image and text
}
SecondView().tabItem {
// tabItem image and text
}
}
}
}
Now, let's say FirstView
contains a NavigationView
with scrollable content using NavigationLink
for each element. How can I make it such that when a NavigationLink
destination is triggered (i.e. a child view is opened), that it takes over the whole page (in full-screen) and thus hides the TabView
?
Ideally I would like to support iOS 13+.
I have tried to follow the guidance at Hacking with Swift but to no avail.
I also followed the advice in SwiftUI Hide TabView bar inside NavigationLink views but found that the top solution is not so performant, so I am hoping to achieve a solution without a delayed appearance.
Enclose the contents of your tabitem
inside an if condition that checks a shared state:
struct ContentView: View {
@StateObject private var state = State()
var body: some View {
TabView {
FirstView().tabItem {
if !state.hideTabView {
// tabItem image and text
}
}
SecondView().tabItem {
if !state.hideTabView {
// tabItem image and text
}
}
}
.environmentObject(state)
}
}
Where State
is an ObservableObject
as such:
class State: ObservableObject {
@Published var hideTabView: Bool = false
}
Then you can use onAppear
on the View that is linked to via NavigationLink
(e.g inside FirstView
):
struct FirstView: View {
@EnvironmentObject private var state: State
var body: some View {
VStack {
// ... some content
}
.onAppear(perform: { state.hideTabView = true })
.onDisappear(perform: { state.hideTabView = false })
}
}
There is a slight delay on the TabView appearing again when you press "< Back", if that really bothers you then you can make a custom Back button and move this state.hideTabView = false
to the event of tapping that button.
That is one approach I can think of :) Also, you might find this thread helpful.