按按钮显示新视图 Swift UI

Show a new View from Button press Swift UI

我希望能够在我的其中一个视图上按下按钮时显示新视图。

从我看过的教程和其他已回答的问题来看,似乎每个人都在导航视图中使用导航按钮,除非我误认为导航视图是给我菜单栏右箭头的那个应用程序,所以我不想要那个。当我将不是 NavigationView 子项的导航按钮放在我的视图中时,它只是在 UI 上被禁用并且我无法单击它,所以我想我不能使用它。

我看到的其他示例似乎使用了演示文稿链接/按钮,它们似乎显示了一种弹出式视图。

我只是在寻找如何单击一个常规按钮并显示另一个全屏视图,就像执行用于执行旧方法的 segue 一样。

对于简单的示例,您可以使用如下所示的东西

import SwiftUI

struct ExampleFlag : View {
    @State var flag = true
    var body: some View {
        ZStack {
            if flag {
                ExampleView().tapAction {
                    self.flag.toggle()
                }
            } else {
                OtherExampleView().tapAction {
                    self.flag.toggle()
                }
            }
        }
    }
}
struct ExampleView: View {
     var body: some View {
        Text("some text")
    }
}
struct OtherExampleView: View {
    var body: some View {
        Text("other text")
    }
}

但是如果你想展示更多视图,这种方式看起来很讨厌

您可以在没有 NavigationView 的情况下使用堆栈来控制视图状态

例如:

    class NavigationStack: BindableObject {
        let didChange = PassthroughSubject<Void, Never>()

        var list: [AuthState] = []

        public func push(state: AuthState) {
            list.append(state)
            didChange.send()
        }
        public func pop() {
            list.removeLast()
            didChange.send()
        }
    }

    enum AuthState {
        case mainScreenState
        case userNameScreen
        case logginScreen
        case emailScreen
        case passwordScreen
    }
    struct NavigationRoot : View {
        @EnvironmentObject var state: NavigationStack
        @State private var aligment = Alignment.leading

        fileprivate func CurrentView() -> some View {
            switch state.list.last {
            case .mainScreenState:
                return AnyView(GalleryState())
            case .none:
                return AnyView(LoginScreen().environmentObject(state))
            default:
                return AnyView(AuthenticationView().environmentObject(state))
            }
        }
        var body: some View {
        GeometryReader { geometry in
            self.CurrentView()
                .background(Image("background")
                    .animation(.fluidSpring())
                    .edgesIgnoringSafeArea(.all)
                    .frame(width: geometry.size.width, height: geometry.size.height,
                           alignment: self.aligment))
                    .edgesIgnoringSafeArea(.all)
                    .onAppear {
                        withAnimation() {
                            switch self.state.list.last {
                            case .none:
                                    self.aligment = Alignment.leading
                            case .passwordScreen:
                                    self.aligment = Alignment.trailing
                            default:
                                    self.aligment = Alignment.center
                            }
                        }
                    }
                }
            .background(Color.black)
        }

}

struct ExampleOfAddingNewView: View {
    @EnvironmentObject var state: NavigationStack
    var body: some View {
            VStack {
                Button(action:{ self.state.push(state: .emailScreen) }){
                Text("Tap me")
            }

        }
    }
}


    struct ExampleOfRemovingView: View {
        @EnvironmentObject var state: NavigationStack
        var body: some View {
            VStack {
                Button(action:{ self.state.pop() }){
                    Text("Tap me")
                }
            }
        }
    }

在我看来这种方式很糟糕,但在 SwiftUI 中导航更糟糕

可能的解决方案

1.if 你想在当前视图的顶部呈现(例如:UIKit 中的呈现样式)

struct ContentView: View {
    @State var showingDetail = false

    var body: some View {
        Button(action: {
            self.showingDetail.toggle()
        }) {
            Text("Show Detail")
        }.sheet(isPresented: $showingDetail) {
            DetailView()
        }
    }
}

2.if 你想重置当前 window 场景堆栈(例如:登录后显示主屏幕)

Button(action: goHome) {
    HStack(alignment: .center) {
        Spacer()
        Text("Login").foregroundColor(Color.white).bold()
        Spacer()
    }
}

func goHome() {
    if let window = UIApplication.shared.windows.first {
        window.rootViewController = UIHostingController(rootView: HomeScreen())
        window.makeKeyAndVisible()
    }
}

3.push 新视图(例如:list->detail,UIKit 的导航控制器)

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DetailView()) {
                    Text("Show Detail View")
                }.navigationBarTitle("Navigation")
            }
        }
    }
}

4.update 当前视图基于@state 属性, (ex:show error message on login failure)

    struct ContentView: View {
        @State var error = true
        var body: some View {
            ...
            ... //login email
            .. //login password
            if error {
                Text("Failed to login")
            }
        }
    }