Navigationview and Navigationlink on Button Click in Swiftui

NavigationView and NavigationLink on button click in SwiftUI?

To fix your issue you need to bind and manage tag with NavigationLink, So create one state inside you view as follow, just add above body.

@State var selection: Int? = nil

Then update your button code as follow to add 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)
}

Meaning is, when selection and NavigationLink tag value will match then navigation will be occurs.

I hope this will help you.

Button with NavigationLink and function call SwiftUI

The answer from Yodagama works if you were trying to present a sheet (because you called your navigation destination SheetView), but if you were trying to navigate to SheetView instead of present a sheet, the following code would do that.

struct LoginView: View {
@State var check = false
@State var answer = false

var body: some View {
NavigationView {
VStack{
Text("it doesn't work")
NavigationLink(destination: SheetView(), isActive: $answer, label: {
Button(action: {
answer = test(value: 2)
}, label: {
Text("Calculate")
})
})



}
}
}

func test(value: Int) -> Bool {

if value == 1 {
check = false
} else {
print("Succes")
check = true
}

return check
}

}

struct SheetView: View {

var body: some View {
NavigationView {
VStack{
Text("Test")
.font(.title)
}
}
}
}

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

iOS SwiftUI - NavigationView NavigationLink: Close view with custom Button

You would use presentationMode.wrappedValue.dismiss(). Take a look at this for more information. Here is how you would use it:

struct Login: View {
@AppStorage("userid") var userid: Int = 0
//Doesn't require anything to be passed in.
@Environment(\.presentationMode) var presentationMode
var body: some View{

VStack{

HStack{

Spacer()

Button(action: {
//Part where view is dismissed
presentationMode.wrappedValue.dismiss()

}) {
Image(systemName: "xmark")
.resizable()

.frame(width: 18, height: 18)
.foregroundColor(Color(UIColor(named: "IconColor")!))
}
.padding(.top, 12.0)
.padding(.trailing, 16.0)
}

Spacer()

}

}
}

You would still call this the same way, with a NavigationLink like in the original question above.

Take a look at this answer for more info on dismissing. Also, note that this will disable the default swipe-back behavior, if you want to re-enable it, take a look here.

How to add buttons next to a Swiftui navigation link

I am taking the answer to your button question from this answer, so please give credit there. It is also possible to use a Button with a programmatically triggered NavigationLink in a .background() as the NavigationLink. That can be tricky to make it look stock, and this solution does what you want. This However, you also asked about the list, and that question is very important to understand.

First, if at all possible, avoid using id: \.self in a List, ForEach, etc. The reason is it is very fragile, and will come back to bite you when you try to delete or move items, or if you have two of the "same" items in the list. You really should be using an identifiable struct for this. For this answer, I am using:

struct Fruit: Identifiable {
let id = UUID()
var type: String
// var color: Color, etc.
}

The view then becomes:

struct FruitListView: View {

// This array can have duplicate fruits and the ForEach is unaffected as the id's are different.
@State var fruits: [Fruit] = [Fruit(type: "apple"),
Fruit(type: "orange"),
Fruit(type: "orange"),
Fruit(type: "banana"),
Fruit(type: "banana"),
Fruit(type: "peach")]

var body: some View {
List {
// Since Fruit conforms to Identifiable, you do not need id:
ForEach(fruits) { fruit in
HStack {
Button {
fruits.removeAll(where: { $0.id == fruit.id })
} label: {
Image(systemName: "circle")
.imageScale(.large)
.foregroundColor(.accentColor)
}
.buttonStyle(PlainButtonStyle()) // This is necessary to capture the click
.frame(width: 40)
// .contentShape makes a larger tap area to take up the height of the row.
.contentShape(Rectangle())
// You can use fruit directly as it is a Fruit and an element of fruits
NavigationLink(destination: Text(fruit.type)) {
Text(fruit.type)
}
}
}
// This is a standard delete. Try implementing it in your code. You will likely get a crash.
.onDelete(perform: delete)
}
}

func delete(at offsets: IndexSet) {
fruits.remove(atOffsets: offsets)
}
}

SwiftUI: How to do additional work when clicking a NavigationLink?

For your described scenario here is the simplest way

NavigationView {
NavigationLink("Click Here", destination:
AnotherView()
.onAppear {
// any action having access to current view context
})
}

Verified as still valid with Xcode 13.3 / iOS 15.4

Navigating to detail view on button click in List Row(TableviewCell) in SwiftUI

  1. Use the .hidden() modifier on the navigationLink to prevent the list item from capturing it's action

  2. Change the .buttonStyle from automatic to something else on the list item to prevent it from capturing the button action. (for example borderless)

Working Demo

struct ContentView: View {
@State var selectedTag: Int?

var body: some View {
NavigationView {
List(1...10, id: \.self) { id in
HStack {
Text("Item \(id: id)")
Spacer()

Button("Show detail") { selectedTag = id }
.background(link(id))
}.buttonStyle(.borderless) /// ⚠️ on the item! **NOT** on the button!!!
}
}
}

func link(id: Int) -> some View {
NavigationLink("",
destination: Text("\(id) Selected"),
tag: id,
selection: $selectedTag
).hidden()
}
}

Button click go another page in swiftui

you could try this to go from LoginView to WelcomeView on your button click in LoginView:

struct LoginView: View {
@State private var showWelcomeView = false

var body: some View {
NavigationView {
VStack {
Button(action: { showWelcomeView = true }) {
Text("Login")
.font(.custom(TextConstant.keyValues.front_name, size: 30))
.foregroundColor(.white)
.fontWeight(.bold)
.frame(minWidth: 0, maxWidth: .infinity)
.padding(.all,20)
.foregroundColor(.blue)
.background(LinearGradient(gradient: Gradient(colors: [.green, .green]), startPoint: .leading, endPoint: .trailing))
.cornerRadius(10)
}
NavigationLink("", destination: WelcomeView(), isActive: $showWelcomeView)
}
}
}
}


Related Topics



Leave a reply



Submit