skip to Main Content

I have a List, each element has its own HStack that contains Button and NavigationLink to the next view but both (checkbox button and navigation link) is activated wherever I click on single HStack element.

That means icon on the button changes when I click on the element but application also loads the next view. The same happens when I want to go to the next view by simply clicking on the NavigationLink. Can you help me separate this two functionalities (checkbox Button and NavigationLink)?

struct ContentView: View {
    @ObservedObject var spendingList: SpendingList
    
    var body: some View {
        NavigationView {
            List {
                ForEach($spendingList.spendings) { $spending in
                    HStack{
                        Button(action: {
                            spending.Bought = !spending.Bought
                        }, label: {
                            if spending.Bought == false {
                                Image(systemName: "square")
                                    .foregroundColor(.accentColor)
                            } else {
                                Image(systemName: "checkmark.square")
                                    .foregroundColor(.accentColor)
                            }
                        })
                        
                        NavigationLink(destination: DetailView(spending: $spending)
                            .navigationTitle(Text(spending.Name)),
                                       label: {
                            Text(spending.Name).frame(maxWidth: .infinity, alignment: .leading)

                            if spending.Price != 0 {
                                Text(String(spending.Price)).frame(maxWidth: .infinity, alignment: .trailing)
                            } else {
                                Text("empty").foregroundColor(.gray)
                            }
                        })
                    }
                }
                .navigationTitle(Text("Spending Priority"))
            }
        }
    }
}

2

Answers


  1. Unfortunately, the parent-view list item becomes the Navigation link. So the button press will never be recorded.

    In iOS 16 you can solve this by replacing the NavigationLink with a Button and pushing an item onto the navigation stack with the Button.

    Documentation: https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types

    Something like this, for example:

    struct ContentView: View {
    
        @State var path: [View] = []
        
        var body: some View {
            NavigationStack(path: $path) {
                List {
                    ForEach($spendingList.spendings) { $spending in
                        HStack {
                            Button(action: {
                                spending.Bought = !spending.Bought
                            }, label: {
                                Image(...)
                            })
                            
                            Button(action: {
                                path.append(DetailView(spending: $spending))
                            }, label: {
                                Text(...)
                            })
                                Text(spending.Name)
                            })
                        }
                    }
                }
                .navigationTitle(Text("Spending Priority"))
                .navigationDestination(for: View.self) { view in
                    view
                }
            }
        }
    }
    
    Login or Signup to reply.
  2. The default Style of Button & NavigationLink makes the whole row click as one. However, using PlainButtonStyle() fixes the issue by making the button clickable & not the cell:

    .buttonStyle(.plain)//to your button & NavigationLink
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search