NavigationLink onTapGesture 和导航未始终触发

Posted

技术标签:

【中文标题】NavigationLink onTapGesture 和导航未始终触发【英文标题】:NavigationLink onTapGesture and navigation not firing consistently 【发布时间】:2020-03-21 06:14:54 【问题描述】:

在 SwiftUI 视图中,我通过创建一个包含包含一些文本的 NavigationView 的 VStack 来实现垂直滚动列表。我通过循环遍历popularFeedTypes 对象来构建它,为popularFeedTypes 对象中的每个项目创建一个NavigationLink。如果用户单击 NavigationLink,则用户将被推送到名为 FeedTypeView 的新视图。你可以看下面的代码。

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)
    

我遇到的问题是,如果我在 NavigationLink 上有一个 onTapGesture 操作,我会在模拟器中体验到不同的行为,具体取决于我单击该行的方式。如果我单击该行右侧的文本或箭头 (>),onTapGesture 会触发,但不会发生导航。如果我单击文本和箭头之间的空间,onTapGesture 不会触发,但会发生导航。如果我删除 onTapGesture 代码,单击三个位置中的任何一个都会导致导航发生。所以我的问题是即使存在 onTapGesture 操作也不应该发生导航吗?无论您单击构成 NavigationLink 的行的位置,onTapGesture 操作也不应该触发吗?

【问题讨论】:

NavigationLink 本质上是一个按钮,因此它会响应触摸,当您在其上添加点击手势时,您将拥有一个试图同时响应两个触摸的视图。点击手势有什么用?也许它可以以更好的方式实现? 希望根据用户点击查询一些数据并将其加载到环境对象中 为什么不在目的地的 onApear() 中启动它? 我想这也可以,我想我需要在进行下一个视图之前做出一些决定,但这可能可以用另一种方式处理。不过,我仍然很好奇,是否可以在导航到另一个视图之前在单击期间触发自定义逻辑。 处理各种触摸非常棘手。您还可以在带有isActive 标志的EmptyView 上使用ButtonNavaigationLinink。然后您可以在Button 的操作中处理您想要在onTapGesture 中处理的任何事情,并将isActive 设置为true 作为最后一件事。 【参考方案1】:

您可以使用 onAppear 来处理点击事件。

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)
    

【讨论】:

【参考方案2】:

如果您想同时执行操作和导航,您可以这样做:

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)
        
    

【讨论】:

不幸的是,这并没有解决我的问题,但听起来很有希望 这个解决方案如何为您工作?我试过了,还是不行 谢谢!在最新的 Swift/SwiftUI 上对我来说就像一个魅力。我使用 LazyVStack 而不是 List,所以它可能是相关的。【参考方案3】:
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)
    

这应该可行。在NavigationLink上使用simultaneousGesture

【讨论】:

应该工作吗?你试过了吗?它不适合我。 @MatheusCâmara - 此代码对我有用。【参考方案4】:

如果你想在你的导航链接被触发之前做一些事情,你可以用tagselection初始化一个导航链接。

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)
            
        
    

【讨论】:

以上是关于NavigationLink onTapGesture 和导航未始终触发的主要内容,如果未能解决你的问题,请参考以下文章

NavigationLink 似乎只占用很小的空间

如何使用返回 NavigationLink 的函数声明协议

如何将 ContextMenu 与 NavigationLink 一起使用?

NavigationLink 和 PresentationLink 错误

NavigationLink 标记和选择未按预期工作

SwiftUI 上的 NavigationLink 两次推送视图