使用 SwiftUI 转到新视图

Go to a new view using SwiftUI

我有一个使用 SwiftUI 的按钮的基本视图,我试图在点击按钮时显示一个新的 screen/view。我该怎么做呢?我是否应该为此视图创建一个委托来告诉应用程序 SceneDelegate 呈现一个新的视图控制器?

import SwiftUI

struct ContentView : View {
    var body: some View {
        VStack {
            Text("Hello World")
            Button(action: {
                //go to another view
            }) {
                Text("Do Something")
                    .font(.largeTitle)
                    .fontWeight(.ultraLight)
            }
        }
    }
}

关键是使用 NavigationView 和 NavigationLink:

import SwiftUI

struct ContentView : View {
    var body: some View {
        NavigationView {
            VStack {
                Text("Hello World")
                NavigationLink(destination: DetailView()) {
                    Text("Do Something")
                }
            }
        }
    }
}

必须创建像 LandmarkDetail() 这样的 DetailView 并调用带有目的地的 NavigationButton 作为 LandmarkDetail()。现在详细视图已打开。

用于将值传递到详细信息屏幕方式。通过发送如下代码。

struct LandmarkList: View {
    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                NavigationButton(destination: LandmarkDetail()) {
                    LandmarkRow(landmark: landmark)
                }
            }
            .navigationBarTitle(Text("Landmarks"))
        }
    }
}

这是在不使用 NavigationView 的情况下呈现视图的另一种方法。这就像 UIKit 的 UIModalPresentationStyle.currentContext.

struct PresenterButtonView: View {
var body: some View {
    PresentationButton(Text("Tap to present"),
                       destination: Text("Hello world"))
}}

OP 在这里得到了多次回答,但我只是想通过显示视图 A 和视图 B 也将使用的数据来展示 SwiftUI 的酷炫方面,您可以通过创建 @ 来传递数据在视图 A 中声明并在视图 B 中使用 @Binding 声明声明相同的变量

struct ViewA : View {
    @State var myItems: [Items]
    var body: some View {
        NavigationView {
            VStack {
                NavigationButton(destination: ViewB(items: $myItems)) {
                    Text("Go To ViewB")
                }
            }
        }
    }
}
struct ViewB : View {
    @Binding var myItems: [Items]
    var body: some View {
        NavigationView {
            List{
                ForEach(myItems.identified(by: \.self)) {
                    Text([=11=].itemName)
                }
            }.navigationBarTitle(Text("My Items"))
        }
    }
}

您不能再使用 NavigationButton。相反,您应该使用 NavigationLink。

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: DetailView()) {
                Text("Push new screen")
            }
        }
    }
}

现在我们可以使用 NavigationLink


文件A:

struct ContentView: View {
var body: some View {
    NavigationView {
        VStack {
            Text("Hello World")
            NavigationLink(destination: secondView()) {
                Text("Hit Me!")
                    .fontWeight(.semibold)
                    .font(.title)
                    .padding()
                    .foregroundColor(.white)
                    .background(LinearGradient(gradient: Gradient(colors: [Color(.white),Color(.blue)]), startPoint: .leading, endPoint: .trailing))
                    .cornerRadius(40)
        }
      }
    }
  }
}

文件 B:

struct secondView: View {
var body: some View {
    VStack {
    VStack(alignment: .leading) {
        Text("Turtle Rock")
            .font(.title)
        HStack(alignment: .top) {
            Text("Joshua Tree National Park")
                .font(.subheadline)
            Spacer()
            Text("California")
                .font(.subheadline)
        }
    }
    .padding()
        Spacer()

    }
  }
}                                                                                                  

这不是这里的最佳答案 - 如果您不想要导航栏,而是一种替代方法。请参阅下面的 ,了解使用 NavigationViewNavigationLink 执行此操作的正常方法。希望这仍然有用或也能为您指明正确的方向。

如果您只是想让 NavigationLinkBinding 一起工作,您可以使用与 isActive 绑定参数相同的 NavigationLink 初始化。

总之,回到答案...


我为此做了一个视图修改器。这也意味着没有导航栏。你可以这样称呼它:

.navigate(to: MainPageView(), when: $willMoveToNextScreen)

这可以附加到任何东西上,所以我通常将它附加到主体的末端,例如:

@State private var willMoveToNextScreen = false

var body: some View {
    VStack {
        /* ... */
    }
    .navigate(to: MainPageView(), when: $willMoveToNextScreen)
}

代码(记得要import SwiftUI):

extension View {
    /// Navigate to a new view.
    /// - Parameters:
    ///   - view: View to navigate to.
    ///   - binding: Only navigates when this condition is `true`.
    func navigate<NewView: View>(to view: NewView, when binding: Binding<Bool>) -> some View {
        NavigationView {
            ZStack {
                self
                    .navigationBarTitle("")
                    .navigationBarHidden(true)

                NavigationLink(
                    destination: view
                        .navigationBarTitle("")
                        .navigationBarHidden(true),
                    isActive: binding
                ) {
                    EmptyView()
                }
            }
        }
        .navigationViewStyle(.stack)
    }
}

我认为 Jake 的回答是 NextView 的基本方法。

而且我认为下面的方法是 简单、正式和动态的 尝试方法,如果您真的需要按下按钮。根据 Paul Hudson's Video,从 10'00" 到 12'00"。

(如果您想通过点击不同的按钮转到不同的视图,则应该转到 12'00" 到 15'00"。) (应该转到 15'00" 到 16'00",如果你想转到第二个视图并自动返回 。)还有更多

这是代码示例。

import SwiftUI

struct ContentView: View {

    @State var areYouGoingToSecondView: Bool // Step 2

    var body: some View {
        NavigationView{ // Step 1

            VStack {

                // Step 3
                NavigationLink(destination: YourSecondView(), isActive: $areYouGoingToSecondView) { EmptyView() }


                Text("Hello World")

                Button(action: {
                    self.areYouGoingToSecondView = true // Step 4

                }) {
                    Text("Do Something (Go To Second View)")
                    .font(.largeTitle)
                    .fontWeight(.ultraLight)
                }
            }
        }
    }
}

如果不想显示navigationView,您可以将其隐藏在目的地。

struct ContentViewA : View {
    var body: some View {
        NavigationView {
            VStack {
                Text("Hello World")
                NavigationLink(destination: ContentViewB()) {
                    Text("Go To Next Step")
                }
            }
        }
    }
}



struct ContentViewB : View {
        var body: some View {
            NavigationView {
                VStack {
                    Text("Hello World B")

                }.navigationBarTitle("")
                .navigationBarHidden(true)
            }
        }
    }

或者如果您想根据条件隐藏它,您可以使用 @State 来更改可见性。

我们可以在 Navigation 中使用 Text 并使其像 Button http://g.recordit.co/CkIkjvikfu.gif

struct HomeContent: View {
    var body: some View {
        NavigationView{
            VStack {
                NavigationLink(
                destination: LoginContentView()) {
                    
                        
                           
                    Text("Login")
                        .font(.title)
                        .foregroundColor(Color.white)
                        .multilineTextAlignment(.center)
                        .frame(width: 300.0, height: 50.0)
                        .background(Color(UIColor.appLightBlue))
                   
                }
                
            }
        }
    }
}

我认为这是最简单明了的方法。 在 UI 工具之后使用 fullScreenCover

Button(action: {
         //code
         }){
           Text("Send")
         }.fullScreenCover(isPresented: self.$model.goToOtherView, content: {
                    OtherView()
                })

要以编程方式导航到 link 而不显示可视元素,请用隐藏的 NavigationLink 覆盖您的视图之一。

在此示例中,UI 将在某些代码将 shouldNavigate 设置为 true 时导航:

struct ProgramaticSample {
    @State var shouldNavigate = false
    
    var body: some View {
        Text("Hello navigation")
            .overlay(NavigationLink(
                destination: DestinationScreen(),
                isActive: $shouldNavigate) {}
                .hidden())
    }
}

如果您想将 NavigationLinkButton 结合使用,您只需禁用该按钮即可触发 NavigationLink

的操作
var body: some View {
    NavigationView {
        NavigationLink(destination: EmptyView()) {
            Button {
                // Action will be ignored
            } label: {
                Text("MyButton")
                    .foregroundColor(.primary)
                    .padding()
            }
            .disabled(true)
        }
    }
}