4
votes

In a SwiftUI view I implemented a vertically scrolling list by creating a VStack that contains a NavigationView that contains some text. I build this by looping through a popularFeedTypes object creating a NavigationLink for each item in the popularFeedTypes object. If a user clicks on the NavigationLink the user is pushed to a new view called FeedTypeView. You can see the code below.

VStack{
    NavigationView{
        List (self.popularFeedTypes.popularFeedTypes!, id: \.self) { feedType in
            NavigationLink(destination: FeedTypeView(feedType: feedType)) {
                Text(feedType.feedType)
            }.onTapGesture {
                print("TAPPED")
            }
        }
        .navigationBarTitle(Text("Discover"), displayMode: .inline)
    }
}

The problem I am experiencing is that if I have an onTapGesture action on the NavigationLink, I experience a different behavior from within the simulator depending upon how I click the row. If I click on the text or on the arrow (>) at the right hand side of the row, the onTapGesture fires off but no navigation occurs. If I click on the space between the text and the arrow, onTapGesture does not fire but navigation occurs. If I remove the onTapGesture code, clicking any of the three places causes navigation to occur. So my question is shouldn't navigation occur even with an onTapGesture action existing? Also shouldn't the onTapGesture action fire off regardless of where you click on the row that makes up the NavigationLink?

4
NavigationLink is essentially a button so it responds to touches, when you add a tap geture onto it you have a single view that is trying to respond to two touches at the same time. What is the use of the tap gesture? Maybe it could be achieved in a better way?LuLuGaGa
The desire was to query some data based upon the user click and load it into an environmentobjectChris Dellinger
Why not kick it off in onApear() in your destination?LuLuGaGa
I guess that would work as well, I was thinking I needed to make some decisions before proceeding to the next view, but that can probably be handled another way. I am still curious though, if it is possible to have customized logic fired off during a click prior to navigating to another view.Chris Dellinger
Handling various touches is very tricky. You could also have a Button and a NavaigationLinink over an EmptyView with isActive flag. Then you could handle anything you wanted to in onTapGesture in the Button's action and set isActive to true as the last thing.LuLuGaGa

4 Answers

1
votes

You can use onAppear to handle tapped event.

VStack {
    NavigationView {
        List(self.popularFeedTypes.popularFeedTypes!, id: \.self) { feedType in
            NavigationLink(
                destination: FeedTypeView(feedType: feedType).onAppear { print("TAPPED") }) {
                Text(feedType.feedType)
            }
        }
        .navigationBarTitle(Text("Discover"), displayMode: .inline)
    }
}
0
votes

If you want to do something before your navigation link is triggered, you can initialize a navigation link with tag and selection.

struct someViewName: View {
    
    @State var navigationLinkTriggerer: Bool? = nil
    @State var navigationLinkFeedType: FeedType
    
    var body: some View {
        VStack {
            NavigationLink(destination: FeedTypeView(feedType: navigationLinkFeedType),
                           tag: true,
                           selection: $navigationLinkTriggerer) {
                EmptyView()
            }
            
            NavigationView {
                List (self.popularFeedTypes.popularFeedTypes!, id: \.self) { feedType in
                    Button(feedType) {
                        // do all you want here
                        print("TAPPED")
                        // then set the navigationLinkTriggerer to value of you navigation link `tag`
                        // in this case tag is equal to `true`
                        // this will trigger the navigation link
                        self.navigationLinkFeedType = feedType
                        self.navigationLinkTriggerer = true
                    }
                }
                .navigationBarTitle(Text("Discover"), displayMode: .inline)
            }
        }
    }
}
-1
votes

If you want to perform both action and navigation simultaneously you can do this:

VStack{
        NavigationView{
            List (self.popularFeedTypes.popularFeedTypes!, id: \.self) { feedType in
                NavigationLink(destination: FeedTypeView(feedType: feedType)) {
                    Text(feedType.feedType)
                }
                .simultaneousGesture(TapGesture().onEnded{
                    print("TAPPED")
                })
            }
            .navigationBarTitle(Text("Discover"), displayMode: .inline)
        }
    }
-2
votes
VStack {
    NavigationView{
        List (self.popularFeedTypes.popularFeedTypes!, id: \.self) { feedType in
            NavigationLink(destination: FeedTypeView(feedType: feedType)) {
                Text(feedType.feedType)
            }
            .simultaneousGesture(TapGesture().onEnded {
                print("TAPPED")
            }
            .buttonStyle(PlainButtonStyle())
        }
        .navigationBarTitle(Text("Discover"), displayMode: .inline)
    }
}

This should work. use simultaneousGesture on NavigationLink