使用“静态导航栏”关闭视图

时间:2020-05-11 22:35:02

标签: ios swift swiftui swiftui-navigationlink

我创建了一个充当导航栏的简单视图,其中包含菜单按钮和一些文本。我将其用作NavigationView外部的顶级元素,这使我能够在所有可见的子页面上使视图保持静态。我尝试不将默认导航栏与导航栏项一起使用的原因是,避免在切换视图时与淡入淡出的动画相处的解雇/创建。

我现在所面临的问题是,当我离开父视图时,将子视图解雇了。我可以将按钮从菜单图标更新为后退图标,但是不会触发按钮的动作。一直在网上寻找是否有人做了类似的事情但没有运气,所以我不确定我试图达到的目标是否可能,或者我是否正以正确的方式进行尝试。即使标头已在根视图中初始化,仍然可以从子视图中调用self.presentationMode.wrappedValue.dismiss()吗?感谢您的帮助,这是我到目前为止所拥有的:

根视图(View1):

struct View1: View {
    @State var showMenuButton: Bool = false
    var body: some View {
        VStack {
            CustomNavigationView(showMenuButton: self.showMenuButton)

            NavigationView {
                NavigationLink(destination: View2()) {
                    Text("View 2")
                }
                .navigationBarTitle("")
                .navigationBarHidden(true)
                .onDisappear(){
                    self.showMenuButton = false
                }
                .onAppear() {
                    self.showMenuButton = true
                }
            }
        }
    }
}

根视图(View2)的子视图:

struct View2: View {
    var body: some View {
        VStack{
            Text("This is View 2")
            .navigationBarTitle("")
            .navigationBarHidden(true)
            NavigationLink(destination: View3()) {
                Text("View 3")
            }
        }
    }
}

视图2(View3)的子视图:

struct View3: View {
    var body: some View {
        VStack{
            Text("This is View 3")
            .navigationBarTitle("")
            .navigationBarHidden(true)
        }
    }
}

自定义导航视图:

struct CustomNavigationView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    var showMenuButton = false
    var body: some View {
        VStack {
            HStack {
                if showMenuButton {
                    Button(action: {
                        //Do Something
                    }) {
                        Image(systemName: "line.horizontal.3")
                        .foregroundColor(.black)
                    }
                } else {
                    Button(action: { self.presentationMode.wrappedValue.dismiss()}) {
                        Image(systemName: "arrow.left")
                        .foregroundColor(.black)
                    }
                }
                Text("Sometext")            
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您在第一个视图中使用的环境对象'presentationMode'无法关闭您推送的视图。每个想要被消除的视图都必须有自己的对象。第一个视图内的对象不属于任何其他推入视图。因此,您需要创建视图模型来管理此任务。

这是示例代码。希望能帮助您解决问题。

class NavigationObserver: ObservableObject {
    private var views: [Int:Binding<PresentationMode>] = [:]
    private var current: Int = 0

    func popView() {
       guard let view = views[current] else {
          return
       }
       view.wrappedValue.dismiss()
       views[current] = nil
       current -= 1
     }

    func pushView(id: Int, newView: Binding<PresentationMode>) {
       guard views[id] == nil else {
          return
       }
       current += 1
       views[id] = newView
     }
   }

struct ContentView: View {
@State var showMenuButton: Bool = false
@ObservedObject var observer = NavigationObserver()
var body: some View {
    VStack {
        CustomNavigationView(observer: self.observer, showMenuButton: self.showMenuButton)

        NavigationView {
            NavigationLink(destination: View2(observer: self.observer)) {
                Text("View 2")
            }
            .navigationBarTitle("")
            .navigationBarHidden(true)
            .onDisappear(){
                self.showMenuButton = false
            }
            .onAppear() {
                self.showMenuButton = true
            }
        }
    }
}}
struct View2: View {
@Environment(\.presentationMode) var presentationMode
@ObservedObject var observer: NavigationObserver
var body: some View {
    VStack{
        Text("This is View 2")
        .navigationBarTitle("")
        .navigationBarHidden(true)
        NavigationLink(destination: View3(observer: self.observer)) {
            Text("View 3")
        }
    }.onAppear {
        self.observer.pushView(id: 1, newView: self.presentationMode)
    }
}}

struct View3: View {
@Environment(\.presentationMode) var presentationMode
@ObservedObject var observer: NavigationObserver
var body: some View {
    VStack{
        Text("This is View 3")
        .navigationBarTitle("")
        .navigationBarHidden(true)
    }.onAppear
        {
            self.observer.pushView(id: 2, newView: self.presentationMode)
        }
}
}

struct CustomNavigationView: View {
@ObservedObject var observer: NavigationObserver
var showMenuButton = false
var body: some View {
    VStack {
        HStack {
            if showMenuButton {
                Button(action: {
                    //Do Something
                }) {
                    Image(systemName: "line.horizontal.3")
                    .foregroundColor(.black)
                }
            } else {
                Button(action: {
                    self.observer.popView()
                }) {
                    Image(systemName: "arrow.left")
                    .foregroundColor(.black)
                }
            }
            Text("Sometext")
        }
    }
}
}

谢谢,X_X