【问题标题】:SwiftUI - NavigationBar in View from NavigationLink quickly showing then disappearingSwiftUI - 视图形式 NavigationLink 中的导航栏快速显示然后消失
【发布时间】:2020-06-16 21:51:35
【问题描述】:

我有一个ContentView,其中包含一个NavigationView,它指向一个DestinationView。我想在ContentView 中隐藏导航栏,但在DestinationView 中显示它。要将其隐藏在 ContentView 中,我将 navigationBarHidden 设置为 true 并给 navigationBarTitle 一个空字符串。 在DestinationView 中,我将navigationBarHidden 设置为false,并将其命名为“DestinationView”。

如果我运行项目并点击NavigationLinkDestinationView 会显示NavigationBar,但在视图出现后很快将其隐藏。有人可以帮我解决这个问题吗?

struct ContentView: View {
    var body: some View {
        NavigationView {
            ZStack {
                Color.red.frame(maxWidth: .infinity, maxHeight: .infinity)
                NavigationLink(destination: DestinationView()) {
                    ZStack {
                        Color.green.frame(width: 200, height: 200)
                        Text("Tap me")
                    }
                }
            }
            .navigationBarTitle("")
            .navigationBarHidden(true)
        }
    }
}

struct DestinationView: View {
    var body: some View {
        List {
            Text("1")
            Text("2")
        }
        .navigationBarTitle("DestinationView")
        .navigationBarHidden(false)
    }
}

【问题讨论】:

  • Xcode 11.4b2 中仍然存在此错误。请向 Apple 提交反馈。
  • 我在 2019 年 12 月 2 日将此报告为 FB7475351,但尚未收到任何反馈。

标签: ios swift xcode uiviewcontroller swiftui


【解决方案1】:

您需要使用变量来实现这一点并将其与您的目的地绑定

struct ContentView: View {
         @State var isNavigationBarHidden: Bool = true
        var body: some View {
            NavigationView {

                ZStack {
                    Color.red.frame(maxWidth: .infinity, maxHeight: .infinity)
                    NavigationLink(destination: DestinationView(isNavigationBarHidden: self.$isNavigationBarHidden)) {
                        ZStack {
                            Color.green.frame(width: 200, height: 200)
                            Text("Tap me")
                        }
                    }

                }
                .navigationBarHidden(self.isNavigationBarHidden)
                .navigationBarTitle("")
                .onAppear {
                    self.isNavigationBarHidden = true
                }
            }
        }
    }

    struct DestinationView: View {
        @Binding var isNavigationBarHidden: Bool
        var body: some View {
            List {
                Text("1")
                Text("2")
            }
            .navigationBarTitle("DestinationView")

            .onAppear {
                self.isNavigationBarHidden = false
            }
        }
    }

【讨论】:

  • 这太棒了!您可以省略.navigationBarHidden(false),因为当绑定更改时父视图会执行此操作。
  • 很好的答案 :) 也学到了一些新东西
  • @jawadAli谢谢你我花了很长时间试图弄清楚这个问题,如果不是你的帖子,我想我不会有,谢谢分享!
  • @Jawad 先生,你救了我的命
  • 这个方案的缺点是不能处理动态创建目的地的情况。我认为下面的@Norman 解决方案更好
【解决方案2】:

安全区域布局指南存在问题

struct ContentView: View {
    var body: some View {
        NavigationView {
            ZStack {
                Color.red.frame(maxWidth: .infinity, maxHeight: .infinity)
                VStack {
                    NavigationLink(destination: DestinationView()) {
                        ZStack {
                            Color.green.frame(width: 200, height: 200)
                            Text("Tap me")
                        }
                    }
                }
            }.edgesIgnoringSafeArea(.all)
            .navigationBarHidden(true)
        }
    }
}

struct DestinationView: View {
    var body: some View {
        VStack {
            List {
                Text("1")
                Text("2")
            }
        }.navigationBarTitle("DestinationView")
        .navigationBarHidden(false)
    }
}

快乐编码...

【讨论】:

    【解决方案3】:

    对我来说,通过视图层次结构传递绑定并不是最佳选择,最好将状态添加到环境变量中。

    class SceneState: ObservableObject {
        @Published var isNavigationBarHidden = true
    }
    
    
    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    ...
        var sceneState = SceneState()
    
    ...
        let contentView = ContentView().environmentObject(sceneState)
    ...
    }
    
    struct ContentView: View {
        var body: some View {
            NavigationView {
                View1()
            }
        }
    }
    
    struct View1: View {
        @EnvironmentObject var sceneState: SceneState
        @State private var showView2: Bool = false
    
        var body: some View {
            VStack {
                Text("NO nav bar.")
                Button("Go to View2") {
                    self.showView2 = true
                }
                NavigationLink(destination: View2(), isActive: $showView2, label: {EmptyView()})
            }
            .navigationBarHidden(self.sceneState.isNavigationBarHidden)
            .navigationBarTitle("")
            .navigationBarBackButtonHidden(self.sceneState.isNavigationBarHidden)
        }
    }
    
    
    struct View2: View {
        @EnvironmentObject var sceneState: SceneState
    
         var body: some View {
            VStack {
                Text("WITH nav bar.")
            }
                .navigationBarHidden(self.sceneState.isNavigationBarHidden)
                .navigationBarTitle("WWDC")
                .navigationBarBackButtonHidden(self.sceneState.isNavigationBarHidden)
                .onAppear {
                    self.sceneState.isNavigationBarHidden = false
            }
        }
    }
    

    【讨论】:

    • 我使用这种方法,我相信这是最好的!
    【解决方案4】:

    编辑:使用accepted answer,因为它是一个非常更清洁的解决方案。


    我遇到了这个错误并最终使用UIViewControllerRepresentable 包装了一个控制器,该控制器在其viewDidAppear 方法中设置导航栏隐藏状态:

    struct ContentView: View {
        var body: some View {
            NavigationView {
                ZStack {
                    Color.red.frame(maxWidth: .infinity, maxHeight: .infinity)
                    NavigationLink(destination: DestinationView()) {
                        ZStack {
                            Color.green.frame(width: 200, height: 200)
                            Text("Tap me")
                        }
                    }
                }
                .navigationBarTitle("")
                .navigationBarHidden(true)
            }
        }
    }
    
    struct DestinationView: View {
        var body: some View {
            List {
                Text("1")
                Text("2")
            }
            .navigationBarTitle("DestinationView")
            .navigationBarHidden(false)
            .background(HorribleHack())
        }
    }
    
    struct HorribleHack: UIViewControllerRepresentable {
        func makeUIViewController(context: Context) -> HorribleHackViewController {
            HorribleHackViewController()
        }
    
        func updateUIViewController(_ uiViewController: HorribleHackViewController, context: Context) {
        }
    }
    
    class HorribleHackViewController: UIViewController {
        override func viewDidAppear(_ animated: Bool) {
            DispatchQueue.main.async {
                self.navigationController?.setNavigationBarHidden(false, animated: false)
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      这个问题实际上有一个非常简单的解决方案。经过多次尝试,我发现你必须将.navigationBarHidden(false) 直接添加到NavigationLink 内的目标视图中,如下所示:

      struct ContentView: View {
          var body: some View {
              NavigationView {
                  ZStack {
                      Color.red.frame(maxWidth: .infinity, maxHeight: .infinity)
                      NavigationLink(destination: DestinationView()
                         .navigationBarHidden(false)) {
                          ZStack {
                              Color.green.frame(width: 200, height: 200)
                              Text("Tap me")
                          }
                      }
                  }
                  .navigationBarTitle("")
                  .navigationBarHidden(true)
              }
          }
      }
      
      struct DestinationView: View {
          var body: some View {
              List {
                  Text("1")
                  Text("2")
              }
              .navigationBarTitle("DestinationView")
              .navigationBarHidden(false)
          }
      }
      

      它会按预期工作,并且在出现后不会消失。

      【讨论】:

        【解决方案6】:

        我在 iOS 14 模拟器上运行此代码并且导航栏没有隐藏,所以我认为这可能是 iOS 13 的问题。我遇到了类似的问题,我的代码导致导航栏在 iOS 13.5 模拟器上消失在 iOS 14.4 模拟器上运行良好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-27
          • 2011-01-13
          • 2020-12-15
          • 2020-09-10
          相关资源
          最近更新 更多