【问题标题】:NavigationLink onTapGesture and navigation not firing consistentlyNavigationLink onTapGesture 和导航未始终触发
【发布时间】: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 上使用Button 和NavaigationLinink。然后您可以在Button 的操作中处理您想要在onTapGesture 中处理的任何事情,并将isActive 设置为true 作为最后一件事。

标签: swiftui


【解决方案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】:

    如果你想在你的导航链接被触发之前做一些事情,你可以用tag和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)
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 2013-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多