SwiftUI:如何使用 NavigationViews 切换到新的导航堆栈
SwiftUI: How to switch to a new navigation stack with NavigationViews
我目前正在使用 SwiftUI Beta 5。我有一个工作流程,其中涉及浏览一系列视图。最后一个视图涉及将大量数据填充到应用程序并结束该特定工作流程的操作。
下载数据后,用户应该能够开始新的工作流程。我想 "forget" 关于旧的 NavigationView,因为一旦工作流完成,通过导航堆栈返回是没有用的。相反,我想导航到 "launch" 视图,它实际上成为新导航视图的根。
如何使用 SwiftUI NavigagationViews 使用导航堆栈中的一个视图导航到具有不同 NavigationView 的另一个视图(并因此成为新导航堆栈的根)?
首先,抱歉,我想 post 一个简单的评论,但信誉点数不够 :(
我刚刚更新了返回根目录的方法
实际上,您的评论让我想到了返回根目录的新方法。有一个新的根视图。如果您强制刷新管理根视图的结构视图,那么它将自动执行您想要的操作。下面只是回到根(没有动画)。您可以调整示例以更改根视图(而不是使用相同的视图)以满足您的需要。
struct DetailViewB: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State var fullDissmiss:Bool = false
var body: some View {
SGNavigationChildsView(fullDissmiss: self.fullDissmiss){
VStack {
Text("This is Detail View B.")
Button(action: { self.presentationMode.wrappedValue.dismiss() } )
{ Text("Pop to Detail View A.") }
Button(action: {
self.fullDissmiss = true
} )
{ Text("Pop two levels to Master View with SGGoToRoot.") }
}
}
}
}
struct DetailViewA: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State var fullDissmiss:Bool = false
var body: some View {
SGNavigationChildsView(fullDissmiss: self.fullDissmiss){
VStack {
Text("This is Detail View A.")
NavigationLink(destination: DetailViewB() )
{ Text("Push to Detail View B.") }
Button(action: { self.presentationMode.wrappedValue.dismiss() } )
{ Text("Pop one level to Master.") }
Button(action: { self.fullDissmiss = true } )
{ Text("Pop one level to Master with SGGoToRoot.") }
}
}
}
}
struct MasterView: View {
var body: some View {
VStack {
Text("This is Master View.")
NavigationLink(destination: DetailViewA() )
{ Text("Push to Detail View A.") }
}
}
}
struct ContentView: View {
var body: some View {
SGRootNavigationView{
MasterView()
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
struct SGRootNavigationView<Content>: View where Content: View {
let cancellable = NotificationCenter.default.publisher(for: Notification.Name("SGGoToRoot"), object: nil)
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
@State var goToRoot:Bool = false
var body: some View {
return
Group{
if goToRoot == false{
NavigationView {
content()
}
}else{
NavigationView {
content()
}
}
}.onReceive(cancellable, perform: {_ in
DispatchQueue.main.async {
self.goToRoot.toggle()
}
})
}
}
struct SGNavigationChildsView<Content>: View where Content: View {
let notification = Notification(name: Notification.Name("SGGoToRoot"))
var fullDissmiss:Bool{
get{ return false }
set{ if newValue {self.goToRoot()} }
}
let content: () -> Content
init(fullDissmiss:Bool, @ViewBuilder content: @escaping () -> Content) {
self.content = content
self.fullDissmiss = fullDissmiss
}
var body: some View {
return Group{
content()
}
}
func goToRoot(){
NotificationCenter.default.post(self.notification)
}
}
这就是我们解决这个问题的方法:我们有一个 main/root/launch 视图,用户可以从中点击一个按钮来启动某种业务流程。这将打开一个 sheet,它会显示模态 pop-up 视图。 (sheet的宽度和高度可以自定义,以占用most/all的屏幕。)
sheet 将有一个 NavigationView。这将允许用户逐步浏览一系列视图,作为其工作流程的一部分。 “呈现”标志作为绑定从主视图传递到每个导航视图。
当用户到达最后一个视图并点击 Submit/Done/Finish 按钮结束该特定工作流时,“呈现”绑定可以设置为 false,这会关闭模态 pop-up,并且 returns 用户返回主视图。
我目前正在使用 SwiftUI Beta 5。我有一个工作流程,其中涉及浏览一系列视图。最后一个视图涉及将大量数据填充到应用程序并结束该特定工作流程的操作。
下载数据后,用户应该能够开始新的工作流程。我想 "forget" 关于旧的 NavigationView,因为一旦工作流完成,通过导航堆栈返回是没有用的。相反,我想导航到 "launch" 视图,它实际上成为新导航视图的根。
如何使用 SwiftUI NavigagationViews 使用导航堆栈中的一个视图导航到具有不同 NavigationView 的另一个视图(并因此成为新导航堆栈的根)?
首先,抱歉,我想 post 一个简单的评论,但信誉点数不够 :(
我刚刚更新了返回根目录的方法
实际上,您的评论让我想到了返回根目录的新方法。有一个新的根视图。如果您强制刷新管理根视图的结构视图,那么它将自动执行您想要的操作。下面只是回到根(没有动画)。您可以调整示例以更改根视图(而不是使用相同的视图)以满足您的需要。
struct DetailViewB: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State var fullDissmiss:Bool = false
var body: some View {
SGNavigationChildsView(fullDissmiss: self.fullDissmiss){
VStack {
Text("This is Detail View B.")
Button(action: { self.presentationMode.wrappedValue.dismiss() } )
{ Text("Pop to Detail View A.") }
Button(action: {
self.fullDissmiss = true
} )
{ Text("Pop two levels to Master View with SGGoToRoot.") }
}
}
}
}
struct DetailViewA: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State var fullDissmiss:Bool = false
var body: some View {
SGNavigationChildsView(fullDissmiss: self.fullDissmiss){
VStack {
Text("This is Detail View A.")
NavigationLink(destination: DetailViewB() )
{ Text("Push to Detail View B.") }
Button(action: { self.presentationMode.wrappedValue.dismiss() } )
{ Text("Pop one level to Master.") }
Button(action: { self.fullDissmiss = true } )
{ Text("Pop one level to Master with SGGoToRoot.") }
}
}
}
}
struct MasterView: View {
var body: some View {
VStack {
Text("This is Master View.")
NavigationLink(destination: DetailViewA() )
{ Text("Push to Detail View A.") }
}
}
}
struct ContentView: View {
var body: some View {
SGRootNavigationView{
MasterView()
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
struct SGRootNavigationView<Content>: View where Content: View {
let cancellable = NotificationCenter.default.publisher(for: Notification.Name("SGGoToRoot"), object: nil)
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
@State var goToRoot:Bool = false
var body: some View {
return
Group{
if goToRoot == false{
NavigationView {
content()
}
}else{
NavigationView {
content()
}
}
}.onReceive(cancellable, perform: {_ in
DispatchQueue.main.async {
self.goToRoot.toggle()
}
})
}
}
struct SGNavigationChildsView<Content>: View where Content: View {
let notification = Notification(name: Notification.Name("SGGoToRoot"))
var fullDissmiss:Bool{
get{ return false }
set{ if newValue {self.goToRoot()} }
}
let content: () -> Content
init(fullDissmiss:Bool, @ViewBuilder content: @escaping () -> Content) {
self.content = content
self.fullDissmiss = fullDissmiss
}
var body: some View {
return Group{
content()
}
}
func goToRoot(){
NotificationCenter.default.post(self.notification)
}
}
这就是我们解决这个问题的方法:我们有一个 main/root/launch 视图,用户可以从中点击一个按钮来启动某种业务流程。这将打开一个 sheet,它会显示模态 pop-up 视图。 (sheet的宽度和高度可以自定义,以占用most/all的屏幕。)
sheet 将有一个 NavigationView。这将允许用户逐步浏览一系列视图,作为其工作流程的一部分。 “呈现”标志作为绑定从主视图传递到每个导航视图。
当用户到达最后一个视图并点击 Submit/Done/Finish 按钮结束该特定工作流时,“呈现”绑定可以设置为 false,这会关闭模态 pop-up,并且 returns 用户返回主视图。