使用 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()
}
}
}
这不是这里的最佳答案 - 如果您不想要导航栏,而是一种替代方法。请参阅下面的 ,了解使用 NavigationView
和 NavigationLink
执行此操作的正常方法。希望这仍然有用或也能为您指明正确的方向。
如果您只是想让 NavigationLink
与 Binding
一起工作,您可以使用与 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())
}
}
如果您想将 NavigationLink
与 Button
结合使用,您只需禁用该按钮即可触发 NavigationLink
的操作
var body: some View {
NavigationView {
NavigationLink(destination: EmptyView()) {
Button {
// Action will be ignored
} label: {
Text("MyButton")
.foregroundColor(.primary)
.padding()
}
.disabled(true)
}
}
}
我有一个使用 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()
}
}
}
这不是这里的最佳答案 - 如果您不想要导航栏,而是一种替代方法。请参阅下面的 NavigationView
和 NavigationLink
执行此操作的正常方法。希望这仍然有用或也能为您指明正确的方向。
如果您只是想让 NavigationLink
与 Binding
一起工作,您可以使用与 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
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())
}
}
如果您想将 NavigationLink
与 Button
结合使用,您只需禁用该按钮即可触发 NavigationLink
var body: some View {
NavigationView {
NavigationLink(destination: EmptyView()) {
Button {
// Action will be ignored
} label: {
Text("MyButton")
.foregroundColor(.primary)
.padding()
}
.disabled(true)
}
}
}