在SwiftUI中单击按钮时的导航视图和导航链接?

lnvxswe2  于 2023-01-16  发布在  Swift
关注(0)|答案(6)|浏览(218)

我试图从登录视图推到详细视图,但无法实现。甚至导航栏也没有显示在登录视图中。如何在SwiftUI中推动按钮点击?如何在按钮点击时使用NavigationLink?

var body: some View {
    
    NavigationView {
        VStack(alignment: .leading) {
            Text("Let's get you signed in.")
                .bold()
                .font(.system(size: 40))
                .multilineTextAlignment(.leading)
                .frame(width: 300, height: 100, alignment: .topLeading)
                .padding(Edge.Set.bottom, 50)
            
            Text("Email address:")
                .font(.headline)
            TextField("Email", text: $email)
                .frame(height:44)
                .accentColor(Color.white)
                .background(Color(UIColor.darkGray))
                .cornerRadius(4.0)
            
            Text("Password:")
                .font(.headline)
            
            SecureField("Password", text: $password)
                .frame(height:44)
                .accentColor(Color.white)
                .background(Color(UIColor.darkGray))
                .cornerRadius(4.0)
            
            Button(action: {
                print("login tapped")
            }) {
                HStack {
                    Spacer()
                    Text("Login").foregroundColor(Color.white).bold()
                    Spacer()
                }
            }
            .accentColor(Color.black)
            .padding()
            .background(Color(UIColor.darkGray))
            .cornerRadius(4.0)
            .padding(Edge.Set.vertical, 20)
        }
        .padding(.horizontal,30)
    }
    .navigationBarTitle(Text("Login"))
}
bf1o4zei

bf1o4zei1#

要解决您的问题,您需要绑定和管理标签与NavigationLink,所以创建一个状态内您的看法如下,只需添加上述机构。

@State var selection: Int? = nil

然后按如下所示更新按钮代码以添加NavigationLink

NavigationLink(destination: Text("Test"), tag: 1, selection: $selection) {
    Button(action: {
        print("login tapped")
        self.selection = 1
    }) {
        HStack {
            Spacer()
            Text("Login").foregroundColor(Color.white).bold()
            Spacer()
        }
    }
    .accentColor(Color.black)
    .padding()
    .background(Color(UIColor.darkGray))
    .cornerRadius(4.0)
    .padding(Edge.Set.vertical, 20)
}

意思是,当选择和NavigationLink标签值匹配时,将发生导航。
希望这对你有帮助。

w8rqjzmb

w8rqjzmb2#

iOS 16及以上版本

  • 注意:下面是如何显示新视图的简化示例。有关更高级的一般示例,请参阅this answer。*

在iOS 16中,我们可以访问NavigationStackNavigationPath

    • 用法#1**

一个简单的NavigationLink命令激活一个新视图:

struct ContentView: View {
    var body: some View {
        NavigationStack {
            NavigationLink(value: "NewView") {
                Text("Show NewView")
            }
            .navigationDestination(for: String.self) { view in
                if view == "NewView" {
                    Text("This is NewView")
                }
            }
        }
    }
}
    • 用法#2**

新视图由标准Button激活:

struct ContentView: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            Button {
                path.append("NewView")
            } label: {
                Text("Show NewView")
            }
            .navigationDestination(for: String.self) { view in
                if view == "NewView" {
                    Text("This is NewView")
                }
            }
        }
    }
}
    • 用法#3**

新视图以编程方式激活:

struct ContentView: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            Text("Content View")
                .navigationDestination(for: String.self) { view in
                    if view == "NewView" {
                        Text("This is NewView")
                    }
                }
        }
        .onAppear {
            path.append("NewView")
        }
    }
}

iOS 13及以上版本

接受的答案使用NavigationLink(destination:tag:selection:),这是正确的。
但是,对于只有一个NavigationLink的简单视图,可以使用simpler变体:NavigationLink(destination:isActive:)

    • 用法#1**

NavigationLink由标准Button激活:

struct ContentView: View {
    @State var isLinkActive = false

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {
                ...
                NavigationLink(destination: Text("OtherView"), isActive: $isLinkActive) {
                    Button(action: {
                        self.isLinkActive = true
                    }) {
                        Text("Login")
                    }
                }
            }
            .navigationBarTitle(Text("Login"))
        }
    }
}
    • 用法#2**

NavigationLink被标准Button * 隐藏 * 并激活:

struct ContentView: View {
    @State var isLinkActive = false

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {
                ...
                Button(action: {
                    self.isLinkActive = true
                }) {
                    Text("Login")
                }
            }
            .navigationBarTitle(Text("Login"))
            .background(
                NavigationLink(destination: Text("OtherView"), isActive: $isLinkActive) {
                    EmptyView()
                }
                .hidden()
            )
        }
    }
}
    • 用法#3**

NavigationLink是 * 隐藏的 *,并通过编程方式激活:

struct ContentView: View {
    @State var isLinkActive = false

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {
                ...
            }
            .navigationBarTitle(Text("Login"))
            .background(
                NavigationLink(destination: Text("OtherView"), isActive: $isLinkActive) {
                    EmptyView()
                }
                .hidden()
            )
        }
        .onAppear {
            self.isLinkActive = true
        }
    }
}

下面是一个GitHub存储库,它具有不同的SwiftUI扩展,使导航更容易。

sg3maiej

sg3maiej3#

另一种方法:

    • 场景代理**
if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: BaseView().environmentObject(ViewRouter()))
            self.window = window
            window.makeKeyAndVisible()
        }
    • 基本视图**
import SwiftUI

struct BaseView : View {

    @EnvironmentObject var viewRouter: ViewRouter

    var body: some View {
        VStack {
            if viewRouter.currentPage == "view1" {
                FirstView()
            } else if viewRouter.currentPage == "view2" {
                SecondView()
                    .transition(.scale)
            }
        }
    }
}

#if DEBUG
struct MotherView_Previews : PreviewProvider {
    static var previews: some View {
        BaseView().environmentObject(ViewRouter())
    }
}
#endif
    • 查看路由器**
import Foundation
import Combine
import SwiftUI

class ViewRouter: ObservableObject {

    let objectWillChange = PassthroughSubject<ViewRouter,Never>()

    var currentPage: String = "view1" {
        didSet {
            withAnimation() {
                objectWillChange.send(self)
            }
        }
    }
}
    • 第一个视图**
import SwiftUI

struct FirstView : View {

    @EnvironmentObject var viewRouter: ViewRouter

    var body: some View {
        VStack {
            Button(action: {self.viewRouter.currentPage = "view2"}) {
                NextButtonContent()
            }
        }
    }
}

#if DEBUG
struct FirstView_Previews : PreviewProvider {
    static var previews: some View {
        FirstView().environmentObject(ViewRouter())
    }
}
#endif

struct NextButtonContent : View {
    var body: some View {
        return Text("Next")
            .foregroundColor(.white)
            .frame(width: 200, height: 50)
            .background(Color.blue)
            .cornerRadius(15)
            .padding(.top, 50)
    }
}
    • 第二个视图**
import SwiftUI

struct SecondView : View {

    @EnvironmentObject var viewRouter: ViewRouter

    var body: some View {
        VStack {
            Spacer(minLength: 50.0)
            Button(action: {self.viewRouter.currentPage = "view1"}) {
                BackButtonContent()
            }
        }
    }
}

#if DEBUG
struct SecondView_Previews : PreviewProvider {
    static var previews: some View {
        SecondView().environmentObject(ViewRouter())
    }
}
#endif

struct BackButtonContent : View {
    var body: some View {
        return Text("Back")
            .foregroundColor(.white)
            .frame(width: 200, height: 50)
            .background(Color.blue)
            .cornerRadius(15)
            .padding(.top, 50)
    }
}

希望这有帮助!

oknrviil

oknrviil4#

最简单有效的解决方案是:

NavigationLink(destination:ScoresTableView()) {
                    Text("Scores")
                }.navigationBarHidden(true)
                    .frame(width: 90, height: 45, alignment: .center)
                    .foregroundColor(.white)
                    .background(LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .leading, endPoint: .trailing))
                    .cornerRadius(10)
                    .contentShape(Rectangle())
                    .padding(EdgeInsets(top: 16, leading: UIScreen.main.bounds.size.width - 110 , bottom: 16, trailing: 20))

ScoresTableView是目标视图。

pvcm50d1

pvcm50d15#

在我看来,**iOS16 +**的一种更干净的方式是使用状态布尔值来表示视图。

struct ButtonNavigationView: View {
    @State private var isShowingSecondView : Bool = false
    
    var body: some View {
        NavigationStack {
            VStack{
                Button(action:{isShowingSecondView = true} ){
                    Text("Show second view")
                }
            }.navigationDestination(isPresented: $isShowingSecondView) {
                Text("SecondView")
            }
        }
    }
}
l2osamch

l2osamch6#

我认为以上答案很好,但更简单的方法应该是:

NavigationLink {
        TargetView()
    } label: {
        Text("Click to go")
    }

相关问题