Go to a new view using SwiftUI

SwiftSwiftui

Swift Problem Overview


I've got a basic view with a button using SwiftUI and I'm trying to present a new screen/view when the button is tapped. How do I do this? Am I suppose to create a delegate for this view that will tell the app's SceneDelegate to present a new view controller?

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)
            }
        }
    }
}

Swift Solutions


Solution 1 - Swift

This was not intended to be the top answer here - but rather an alternative method if you didn't want the navigation bar. See Jake's answer below for the normal way to do this with NavigationView & NavigationLink. Hopefully this is still useful or points you in the right direction too.

If you are just trying to get a NavigationLink working with a Binding, you can use the same NavigationLink init I did with the isActive binding parameter.

Anyway, back to the answer…


I made a view modifier for this. It also means that there is no navigation bar. You can call it like so:

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

This can be attached to anything, so I typically attach it to the end of the body, for example:

@State private var willMoveToNextScreen = false

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

Code (remember to 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)
    }
}

Solution 2 - Swift

The key is to use a NavigationView and a NavigationLink:

import SwiftUI

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

Solution 3 - Swift

if don't want to show the navigationView you can hide it in destination.

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)
            }
        }
    }

or if you want to hide it based on conditions you can use @State for changing the visibility.

Solution 4 - Swift

Here's another way to present a view WITHOUT using NavigationView. This is like UIKit's UIModalPresentationStyle.currentContext.

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

Solution 5 - Swift

Now we can use NavigationLink


File 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)
        }
      }
    }
  }
}

File 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()
        
    }
  }
}                                                                                                  

Solution 6 - Swift

I think this is the easiest and clear way. Use fullScreenCover after UI tool.

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

Solution 7 - Swift

The OP has been answered multiple times here but I just wanted to also demonstrate the cool aspects of SwiftUI by showing if you have view A with data that view B will also be using, you can pass data by creating a @State in view A and declaring the same variable with @Binding declaration in view B

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($0.itemName)
                }
            }.navigationBarTitle(Text("My Items"))
        }
    }
}

Solution 8 - Swift

You can no longer use NavigationButton. Instead you should use NavigationLink.

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

Solution 9 - Swift

I think Jake's answer is the basic way to NextView.

And I think the way bellow is a simple, formal, and dynamic way to try, if you really need to hit a BUTTON. According to Paul Hudson's Video, from 10'00" to 12'00".

(should go to 12'00" to 15'00", if you want to go to different views by tapping different buttons.) (should go to 15'00" to 16'00", if you want to go to second view and go back automatically.) And more

And here is the code example.

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)
                }
            }
        }
    }
}

Solution 10 - Swift

We can use Text inside Navigation and make it like Button enter image description here 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))
                   
                }
                
            }
        }
    }
}

Solution 11 - Swift

To programmatically navigate to a link without displaying a visual element, overlay one of your views with a hidden NavigationLink.

In this sample, the UI will navigate when some code sets shouldNavigate to true:

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

Solution 12 - Swift

Have to create a DetailView like LandmarkDetail() and call a NavigationButton with destination as LandmarkDetail(). Now detail view was open.

For passing values to detail screen means. by sending like below code.

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

Solution 13 - Swift

If you want to use NavigationLink in combination with Button you could just disable the button to trigger the action of the NavigationLink

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJakeView Question on Stackoverflow
Solution 1 - SwiftGeorgeView Answer on Stackoverflow
Solution 2 - SwiftJakeView Answer on Stackoverflow
Solution 3 - SwiftMohsen mokhtariView Answer on Stackoverflow
Solution 4 - SwiftSadaView Answer on Stackoverflow
Solution 5 - SwiftDharmesh MansataView Answer on Stackoverflow
Solution 6 - SwiftbulutgonulalanView Answer on Stackoverflow
Solution 7 - SwiftnikoclicksView Answer on Stackoverflow
Solution 8 - SwiftEdwardView Answer on Stackoverflow
Solution 9 - SwiftBraver ChiangView Answer on Stackoverflow
Solution 10 - SwiftVarun NahariaView Answer on Stackoverflow
Solution 11 - SwiftEdward BreyView Answer on Stackoverflow
Solution 12 - SwiftKathiresan MuruganView Answer on Stackoverflow
Solution 13 - SwiftPatrickDotStarView Answer on Stackoverflow