从 Button 按 Swift UI 显示新视图

Ang*_*uck 8 swiftui

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

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

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

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

小智 7

可能的解决方案

1.如果你想在当前视图之上呈现(例如:UIKit中的呈现样式)

struct ContentView: View {
    @State var showingDetail = false

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

2.如果要重置当前窗口场景堆栈(例如:登录后显示主屏幕)

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

3.push new view (ex: list->detail, UIKit 的导航控制器)

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

4.根据@state属性更新当前视图,(例如:登录失败时显示错误信息)

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


Rad*_*ast 4

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

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

但如果你想呈现更多视图,这种方式看起来很糟糕

您可以使用堆栈来控制视图状态,而无需使用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")
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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