I'm using TabView
on my home page. Let's just say I have 4 tabs.
On second tab, i can go to another view using NavigationLink
and I go to another 2 views using NavigationLink
. Then on the latest view, there is a button to present a view and i use .fullScreenCover
(since I want to present it full screen).
In the presenting view, I add an X
mark on the left side of the navigationBarItems
to dismiss. I use @Environment(\.presentationMode) var presentationMode
and presentationMode.wrappedValue.dismiss()
to dismiss. But it only dismiss the presenting view to the previous view, while actually I want to dismiss it to the root of my view which is the 2nd tab of my TabView
.
Is there a way to do this? Because I have looked up to some articles and nothing relevant especially in TabView
context.
I also have a question tho:
.fullScreenCover
? Or is there another possible solution for example presenting a modal with full screen style (if there's any cause i'm not sure either).Any suggestions will be very appreciated, thankyou in advance.
wrappedValue. dismiss() from that child view will pop to the root view.
Press Cmd+N to create a new SwiftUI View, calling it “MainView”. Creating tabs is as easy as putting different views inside an instance of TabView , but in order to add an image and text to the tab bar item of each view we need to use the tabItem() modifier.
The presentationMode
is one-level effect value, ie changing it you close one currently presented screen.
Thus to close many presented screens you have to implement this programmatically, like in demo below.
The possible approach is to use custom EnvironmentKey
to pass it down view hierarchy w/o tight coupling of every level view (like with binding) and inject/call only at that level where needed.
Demo tested with Xcode 12.4 / iOS 14.4
struct ContentView: View {
var body: some View {
TabView {
Text("Tab1")
.tabItem { Image(systemName: "1.square") }
Tab2RootView()
.tabItem { Image(systemName: "2.square") }
}
}
}
struct Tab2RootView: View {
@State var toRoot = false
var body: some View {
NavigationView {
Tab2NoteView(level: 0)
.id(toRoot) // << reset to root !!
}
.environment(\.rewind, $toRoot) // << inject here !!
}
}
struct Tab2NoteView: View {
@Environment(\.rewind) var rewind
let level: Int
@State private var showFullScreen = false
var body: some View {
VStack {
Text(level == 0 ? "ROOT" : "Level \(level)")
NavigationLink("Go Next", destination: Tab2NoteView(level: level + 1))
Divider()
Button("Full Screen") { showFullScreen.toggle() }
.fullScreenCover(isPresented: $showFullScreen,
onDismiss: { rewind.wrappedValue.toggle() }) {
Tab2FullScreenView()
}
}
}
}
struct RewindKey: EnvironmentKey {
static let defaultValue: Binding<Bool> = .constant(false)
}
extension EnvironmentValues {
var rewind: Binding<Bool> {
get { self[RewindKey.self] }
set { self[RewindKey.self] = newValue }
}
}
struct Tab2FullScreenView: View {
@Environment(\.presentationMode) var mode
var body: some View {
Button("Close") { mode.wrappedValue.dismiss() }
}
}
backup
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With