Go to a New View Using Swiftui

Go to a new view using SwiftUI

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

SwiftUI - Opening a new view on button click

A NavigationLink must be in view hierarchy, so instead of putting it in action we need to put some model there.

A sketch of possible approach

  1. destination model
enum MenuDestination: String, CaseIterable, Hashable {
case set1(MenuItem), set2

@ViewBuilder var view: some View {
switch self {
case .set1(let item): View1(item: item)
case .set2: SettingsView()
}
}
}

  1. navigation link in view
    @State private var selection: MenuDestination?
var isActive: Binding<Bool> {
Binding(get: { selection != nil }, set: { selection = nil } )
}

var body: some View {
NavigationView {
ScrollView {
// ...
}
.background(
if let selection = selection {
NavigationLink(isActive: isActive, destination: { selection.view }) {
EmptyView()
}})
}
}

  1. button action assigns corresponding value, say MenuItemAction take as argument binding to selection and internally assign destination to that binding
MenuItemCircularGridView(imageName: item.imageName, menuItemName: item.name, 
action: (menuOptionsAction.menuActions.first {$0.id == item.id})?.action($selection) ?? { _ in })

and MenuItemAction inited with case of corresponding MenuDestination

See also this post

Trying to move to a new view in swiftUI after a button press

to make the "move work", add this to "AddAssignment":

struct AddAssignment: View {
@State var toAssignment: Int? = nil

replace your Button("Create New Task", action: {...}, with

        NavigationLink(destination: ViewAssignment(), tag: 1, selection: $toAssignment) {
Button("Create New Task") {
let task: [String] = [taskName, dueDate, subject, weighting, totalMarks]
print(task)
self.toAssignment = 1
}
}

make sure you wrap the whole thing in "NavigationView { ...}"

How To Switch To A New View On Simple Button Click?

The best way would be to use a NavigationLink and wrapping the content inside a NavigationView.

The NavigationView is used to represent the view hierarchy.

For instance:

// Wrapper for LogIn
struct ContentView: View {
var body: some View {
NavigationView { LogIn() }
}
}

// LogIn
struct LogIn: View {
var body: some View {
VStack {
// Fields for log in

NavigationLink(destination: SignUp()) {
Text("Create New Account")
.foregroundColor(.white)
.font(.title)
.frame(maxWidth: .infinity, alignment: .center)
.background(Color(red: 0.22, green: 0.655, blue: 0.02))
.cornerRadius(8)
.padding(.horizontal, metrics.size.width*0.10)
}
}
}
}

You can find more info in the official docs:

  • NavigationView
  • NavigationLink

Also [Hacking With Swift] (https://www.hackingwithswift.com/quick-start/swiftui/displaying-a-detail-screen-with-navigationlink) is a great resource for SwiftUI

Programmatically navigate to new view in SwiftUI

You can replace the next view with your login view after a successful login. For example:

struct LoginView: View {
var body: some View {
...
}
}

struct NextView: View {
var body: some View {
...
}
}

// Your starting view
struct ContentView: View {

@EnvironmentObject var userAuth: UserAuth

var body: some View {
if !userAuth.isLoggedin {
LoginView()
} else {
NextView()
}

}
}

You should handle your login process in your data model and use bindings such as @EnvironmentObject to pass isLoggedin to your view.

Note: In Xcode Version 11.0 beta 4, to conform to protocol 'BindableObject' the willChange property has to be added

import Combine

class UserAuth: ObservableObject {

let didChange = PassthroughSubject<UserAuth,Never>()

// required to conform to protocol 'ObservableObject'
let willChange = PassthroughSubject<UserAuth,Never>()

func login() {
// login request... on success:
self.isLoggedin = true
}

var isLoggedin = false {
didSet {
didChange.send(self)
}

// willSet {
// willChange.send(self)
// }
}
}

Show a new View from Button press Swift UI

For simple example you can use something like below

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

but if you want to present more view this way looks nasty

You can use stack to control view state without NavigationView

For Example:

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

In my opinion this bad way, but navigation in SwiftUI much worse

iOS SwiftUI - NavigationLink open new view and close the current one

In order to do this, I would suggest skipping the NavigationView altogether, see here for more info. An example for your situation:

//You need an `ObservedObject` to do this, and a overall holder view

enum ViewStates{
//Declare possible views
case ContentView
case Login
case CreateAccount

}

//Then use an observableObject

class viewControl: ObservableObject{
@Published var currentView: ViewStates = .ContentView
}

//Finally, pass this into your views. Take a look at the second part of the tutorial I posted below for more info
//such as using `EnvironmentObject` and adding animation. Example implimentation below:


struct ControllerView: View{
@StateObject var controller: viewControl

var body: some View{
switch controller.currentView{
case .ContentView:
ContentView(controller: controller)
case .Login:
Login(controller: controller)
case .CreateAccount:
CreateAccount(controller: controller)
}
}

}

Next, you need to have @ObservedObject var controller: viewControl in all of your views. Note that you don't need a default statement in the switch clause, because the enum declares all possible values. The following is an example CreateAccount view. You also no longer need the dismiss - in fact, that will no longer work.

struct CreateAccount: View{
@ObservedObject var controller: viewControl

var body: some View{
//Content
Button("Dismiss"){
controller.currentView = .ContentView
}
}

}

This will allow you to switch the view by clicking. Instead of a NavigationLink in ContentView, do this:

Button{
controller.currentView = .CreateAccount
} label: {
Text("Create Account")
}

To go back, you just set the value again. This can also be expanded to show more views.

Second part of the tutorial



Related Topics



Leave a reply



Submit