SwiftUI中导航栏隐藏无法正常工作

15

我有三个视图,我想在第三个视图中隐藏导航栏。即使我使用 .navigationBarHidden(true),导航栏仍然显示!

我找不到我的错误所在。下面是我的代码和结果截图。

Xcode 版本 - 11.1

struct ContentViewOne: View {
    var body: some View {
        NavigationView {
            ZStack {
                
                Color.yellow.edgesIgnoringSafeArea(.all)
                VStack(spacing: 20) {
                    Text("View One")
                    
                    NavigationLink(destination: ContentViewTwo()) {
                        Text("Navigate to View Two")
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.red)
                    }
                }
            }
            .navigationBarTitle("View One")
        }
    }
}

struct ContentViewTwo: View {
    var body: some View {
        
        ZStack {
            Color.green.edgesIgnoringSafeArea(.all)
            VStack(spacing: 20) {
                Text("View Two")
                NavigationLink(destination: ContentViewThree()) {
                    Text("Navigate to View Three")
                        .foregroundColor(.white)
                        .padding()
                        .background(Color.red)
                }
            }
        }
        .navigationBarTitle("View Two")
    }
}

struct ContentViewThree: View {
    var body: some View {
        ZStack {
            Color.gray.edgesIgnoringSafeArea(.all)
            Text("View Three")
        }
        .navigationBarTitle("View Three")
        .navigationBarHidden(true)
        .navigationBarBackButtonHidden(true)
    }
}

在此输入图像描述


https://dev59.com/Pl4b5IYBdhLWcg3wZwu3 - Ernist Isabekov
9个回答

43

注意:(原因未知)SwiftUI 要求您需要使用 .navigationBarTitle,才能使 .navigationBarHidden 正常工作。

NavigationView {
    ScrollView() {
     ......
    }.  
    .navigationBarTitle("") //this must be empty
    .navigationBarHidden(true)
    .navigationBarBackButtonHidden(true)
}

在 TabBar 中的视图中添加 .navigationBarTitle("") 后,选择该选项卡时该选项卡的标签将被擦除。我的做法是重新设置选项卡的标签而不是 ""。 - Alan Steiman
同时还收到一个警告消息:"在动画过程中更改项目可能会导致导航栏损坏"。 - zdravko zdravkin
4
在我的情况下,将 .navigationBarHidden 添加到 ScrollView 上起了作用。 - jonye._.jin
3
在iOS 15中无法工作。 - Tanvirgeek
@Tanvirgeek让我检查并更新。 - Rohit Makwana
显示剩余3条评论

6

我尝试了多种解决方案,包括UINavigationControllerDelegate,但似乎没有一种可以永久隐藏navigationBar。 直到我尝试了KVO :)

因此,如果您想要一个永久的解决方案,请使用以下方法:

struct NoBarNavigationView<Content: View>: View {

    private let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    var body: some View {
        NavigationView {
            content
                .introspectNavigationController { (UINavigationController) in
                    NavigationControllerDelegate.shared.becomeDelegate(of: UINavigationController)
                }
        }
    }
}

class NavigationControllerDelegate: NSObject {

    static let shared = NavigationControllerDelegate()

    func becomeDelegate(of navigationController: UINavigationController) {
        navigationController.isNavigationBarHidden = true
        navigationController.navigationBar.isHidden = true
        navigationController.navigationBar.addObserver(self, forKeyPath: "alpha", options: .new, context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        // This is necessary to ensure the UINavigationBar remains hidden
        if let navigationBar = object as? UINavigationBar {
            navigationBar.isHidden = true
        }
    }

}

愉快地编程吧!

编辑:如评论中所指出,我正在使用:

import Introspect

GitHub链接


1
你应该展示 import Introspect 并且提供 链接 到 GitHub。 - George
没有其他方法对我有效。谢谢! - Lit Climbing
哇,这正是我长期以来一直在寻找的东西,而且这是迄今为止唯一有效的方法!非常感谢! - dreampowder

4

为了更好地处理SwiftUI NavigationBar不隐藏或隐藏时仍占用空间的问题,我在这里发布了此帖:

.navigationBarHidden(true)
.navigationBarTitle("", displayMode: .inline)
.edgesIgnoringSafeArea([.top, .bottom])

这会设置一个标题(有时需要针对旧的SwiftUI版本进行hack),隐藏导航栏,但也告诉渲染引擎忽略任何为导航栏预留空间的安全区域。


单独一行 .navigationBarTitle("", displayMode: .inline) 对我来说就足够了。 重要的是在 .navigationBarHidden(true) 之后设置它。 - CedricSoubrie
1
这对我来说是一个解决方案。我甚至没有导航视图。 - mgyky

3
使用iOS 15.5和15.6时,.navigationBarHidden(true)无效。添加.navigationBarTitle("", displayMode: .inline)也没有帮助。显然这是iOS 15中的一个错误。 iOS 16已经修复了这个问题! 在使用Xcode 14模拟iOS 15.5、iPhone w/ iOS 15.6以及在iPhone X上使用iOS 16进行测试后,该问题已在iOS 16中被修复。

2

要在第三个视图中特别隐藏NavigationBar,您需要删除.navigationBarTitle("View Three"),然后该栏将被隐藏:

struct ContentViewThree: View {
    var body: some View {
        ZStack {
            Color.gray.edgesIgnoringSafeArea(.all)
            Text("View Three")
        }
        .navigationBarHidden(true)
        .navigationBarBackButtonHidden(true)
    }
}

1
你需要在navigationView上添加.navigationBarHidden(true),或者如果你有NavigationLink,你需要在Link上添加。
   NavigationLink("",
                               destination: Text("TEST"),
                               tag: linkValue,
                               selection: $linksNavigator.selection)
                    **.navigationBarHidden(true)**

哇,这是一个非常奇怪的行为,必须为页面上所有导航链接设置“navigationbarHidden”。 - andrei
我发现这也会隐藏持有导航链接的视图上的导航栏(可能是因为子视图继承了父视图的状态?) - sally2000
2
很遗憾,这对我没有起作用 :( - Rachael

0
在iOS 15中,您可以使用@State属性来切换状态。
@State private var hideNavigationbar: Bool = false

你可以在 .onAppear {} 中将值切换为 true。当你关闭视图时,调用 .onDisappear {} 并将属性设置为 false。

现在你可以这样使用它:

.navigationbarHidden(hideNavigationbar)

0

因为你应该将隐藏属性添加到DetailView而不是NavigationLink中,

 NavigationLink(destination: DetailView(mData: sportData)
                                .navigationBarTitle("")
                                .navigationBarHidden(true)
                                .navigationBarBackButtonHidden(true)
                
                ) {
                    Image("arrowRight3").resizable()
                    //.padding(5)
                    //.background(.red)
                       

0

最新的隐藏方法,适用于iOS15


.navigationBarHidden(true)
.ignoresSafeArea()



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接