161

我是SwiftUI的新手(像大多数人一样)并试图弄清楚如何删除List我嵌入在NavigationView.

在此图像中,您可以看到List.

当前版本

我想要完成的是:

理想版

我试过使用:

.navigationBarHidden(true)

但这并没有产生任何明显的变化。

我目前正在像这样设置我的 navigiationView:

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
        .navigationBarHidden(true)
}

定义如下FileBrowserView的 aList和s 视图在哪里:FileCell

List {
   Section(header: Text("Root")) {
       FileCell(name: "Test", fileType: "JPG",fileDesc: "Test number 1")
       FileCell(name: "Test 2", fileType: "txt",fileDesc: "Test number 2")
       FileCell(name: "test3", fileType: "fasta", fileDesc: "")
    }
}

我确实想指出,这里的最终目标是您将能够单击这些单元格以更深入地导航到文件树中,因此应该在更深入的导航栏上显示一个后退按钮,但我不想要任何东西在我最初的看法中也是如此。

4

22 回答 22

216

出于某种原因,SwiftUI 要求您也设置.navigationBarTitlefor.navigationBarHidden才能正常工作。

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
        .navigationBarTitle("")
        .navigationBarHidden(true)
}

更新

正如@Peacemoon 在评论中指出的那样,当您在导航堆栈中更深入地导航时,无论您是否在后续视图中设置navigationBarHidden为,导航栏都会保持隐藏状态。false正如我在评论中所说,这要么是 Apple 执行不力的结果,要么只是可怕的文档(谁知道呢,也许有一种“正确”的方式来实现这一点)。

无论如何,我想出了一个似乎可以产生原始海报所需结果的解决方法。我犹豫是否推荐它,因为它似乎不必要地hacky,但没有任何隐藏和取消隐藏导航栏的直接方法,这是我能做的最好的。

此示例使用三个视图 -View1有一个隐藏的导航栏,View2并且View3两者都有带有标题的可见导航栏。

struct View1: View {
    @State var isNavigationBarHidden: Bool = true

    var body: some View {
        NavigationView {
            ZStack {
                Color.red
                NavigationLink("View 2", destination: View2(isNavigationBarHidden: self.$isNavigationBarHidden))
            }
            .navigationBarTitle("Hidden Title")
            .navigationBarHidden(self.isNavigationBarHidden)
            .onAppear {
                self.isNavigationBarHidden = true
            }
        }
    }
}

struct View2: View {
    @Binding var isNavigationBarHidden: Bool

    var body: some View {
        ZStack {
            Color.green
            NavigationLink("View 3", destination: View3())
        }
        .navigationBarTitle("Visible Title 1")
        .onAppear {
            self.isNavigationBarHidden = false
        }
    }
}

struct View3: View {
    var body: some View {
        Color.blue
            .navigationBarTitle("Visible Title 2")
    }
}

在导航堆栈中设置navigationBarHiddenfalse更深的视图似乎并没有正确覆盖最初设置navigationBarHidden为的视图的首选项true,所以我能想出的唯一解决方法是使用绑定来更改原始视图的首选项。视图被推送到导航堆栈上。

就像我说的,这是一个 hacky 解决方案,但没有 Apple 的官方解决方案,这是我能想到的最好的解决方案。

于 2019-08-16T02:38:50.870 回答
31

视图修改器使它变得容易:

//ViewModifiers.swift

struct HiddenNavigationBar: ViewModifier {
    func body(content: Content) -> some View {
        content
        .navigationBarTitle("", displayMode: .inline)
        .navigationBarHidden(true)
    }
}

extension View {
    func hiddenNavigationBarStyle() -> some View {
        modifier( HiddenNavigationBar() )
    }
}

例子: 在此处输入图像描述

import SwiftUI

struct MyView: View {
    var body: some View {
        NavigationView {
            VStack {
                Spacer()
                HStack {  
                    Spacer()
                    Text("Hello World!")
                    Spacer()
                }
                Spacer()
            }
            .padding()
            .background(Color.green)
            //remove the default Navigation Bar space:
            .hiddenNavigationBarStyle()
        }
    }
}
于 2020-03-02T15:37:25.807 回答
27

a 的目的NavigationView是在视图顶部添加导航栏。在 iOS 中,导航栏有两种:大的和标准的。

在此处输入图像描述

如果你不想导航栏:

FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))

如果您想要一个大导航栏(通常用于您的顶级视图):

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
    .navigationBarTitle(Text("Title"))
}

如果您想要一个标准(内联)导航栏(通常用于子级视图):

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
    .navigationBarTitle(Text("Title"), displayMode: .inline)
}

希望这个答案对您有所帮助。

更多信息:Apple 文档

于 2019-08-16T02:38:04.590 回答
14

如果将标题设置为要删除空间的视图的内联,则不需要在具有 NavigationView 的视图上执行此操作,但导航视图也需要。

.navigationBarTitle("", displayMode: .inline)

开始问题 解决方案 1 然后只需更改导航栏的外观

init() {
    UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
    UINavigationBar.appearance().shadowImage = UIImage()
}

在包含初始 NavigationView 的视图上。 最终解决方案

如果要在屏幕之间更改外观,请在相应视图中更改外观

于 2020-08-14T12:29:03.883 回答
13

SwiftUI 2

有一个专门的修饰符可以使导航栏占用更少的空间:

.navigationBarTitleDisplayMode(.inline)

编辑

在某些情况下,可能仍需要添加.navigationBarHidden(true)

于 2020-11-02T20:38:47.983 回答
11

对我来说,我是在应用.navigationBarTitletoNavigationView而不是 toList是罪魁祸首。这适用于 Xcode 11.2.1:

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: DetailView()) {
                    Text("I'm a cell")
                }
            }.navigationBarTitle("Title", displayMode: .inline)
        }
    }
}

顶部没有间隙的导航栏和列表

于 2020-02-12T14:25:09.230 回答
10

我还尝试了此页面上提到的所有解决方案,只发现 @graycampbell 解决方案运行良好,动画效果良好。因此,我尝试创建一个可以在整个应用程序中使用的值,我可以通过hackingwithswift.com的示例在任何地方访问它

我创建了一个ObservableObject

class NavBarPreferences: ObservableObject {
    @Published var navBarIsHidden = true
}

并将其传递给SceneDelegate像这样的初始视图

var navBarPreferences = NavBarPreferences()
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(navBarPreferences))

然后ContentView我们可以像这样跟踪这个 Observable 对象并创建一个链接SomeView

struct ContentView: View {
    //This variable listens to the ObservableObject class
    @EnvironmentObject var navBarPrefs: NavBarPreferences

    var body: some View {
        NavigationView {
                NavigationLink (
                destination: SomeView()) {
                    VStack{
                        Text("Hello first screen")
                            .multilineTextAlignment(.center)
                            .accentColor(.black)
                    }
                }
                .navigationBarTitle(Text(""),displayMode: .inline)
                .navigationBarHidden(navBarPrefs.navBarIsHidden)
                .onAppear{
                    self.navBarPrefs.navBarIsHidden = true
            }
        }
    }
}

然后在访问第二个视图(SomeView)时,我们再次隐藏它,如下所示:

struct SomeView: View {
    @EnvironmentObject var navBarPrefs: NavBarPreferences

    var body: some View {
        Text("Hello second screen")
        .onAppear {
            self.navBarPrefs.navBarIsHidden = false
        }
    } 
}

要保持预览正常工作,请将 NavBarPreferences 添加到预览中,如下所示:

struct SomeView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView().environmentObject(NavBarPreferences())
    }
}
于 2020-05-28T20:52:57.557 回答
9

这是 SwiftUI 中存在的一个错误(仍然是 Xcode 11.2.1)。我ViewModifier根据现有答案中的代码编写了一个来解决这个问题:

public struct NavigationBarHider: ViewModifier {
    @State var isHidden: Bool = false

    public func body(content: Content) -> some View {
        content
            .navigationBarTitle("")
            .navigationBarHidden(isHidden)
            .onAppear { self.isHidden = true }
    }
}

extension View {
    public func hideNavigationBar() -> some View {
        modifier(NavigationBarHider())
    }
}
于 2019-11-24T15:50:05.670 回答
7

您可以像这样扩展本机View协议:

extension View {
    func hideNavigationBar() -> some View {
        self
            .navigationBarTitle("", displayMode: .inline)
            .navigationBarHidden(true)
    }
}

然后只需调用例如:

ZStack {
    *YOUR CONTENT*
}
.hideNavigationBar()
于 2020-01-22T16:03:56.387 回答
7

将以下代码放在您的 NextView 上

        .navigationBarBackButtonHidden(true)
        .navigationBarHidden(true)

但是在通过 NavigationLink 推送到 NextView 时,您还必须像这样放置修饰符:

        NavigationLink(
            destination: NextView()
                .navigationBarTitle("")
                .navigationBarHidden(true)
        ) {
            Text("NEXT VIEW")
        }
                    
于 2021-04-01T16:07:00.800 回答
6

对我来说,这是因为我正在从现有的 NavigationView 推送。实际上有一个在另一个里面。如果您来自 NavigationView,则不需要在下一个中创建一个,因为您已经在 NavigatonView 中。

于 2020-02-19T08:48:36.390 回答
4

我对这个问题的解决方案与@Genki 和@Frankenstein 建议的相同。

我对内部列表(不是 NavigationView)应用了两个修饰符以消除间距:

.navigationBarTitle("", displayMode: .automatic)
.navigationBarHidden(true) 

在外层 NavigationView 上,然后应用.navigationBarTitle("TITLE")设置标题。

于 2020-08-31T01:34:03.017 回答
3

我尝试设置 .navigationBarTitle("", displayMode: .inline) .navigationBarHidden(true) 但它不起作用。问题是我将其设置为

NavigationView{...}.navigationBarTitle("", displayMode: .inline)
        .navigationBarHidden(true)

但是要摆脱 NagigationBar 它应该设置为它的内部视图

NavigationView{
InnerView{}.navigationBarTitle("", displayMode: .inline)
        .navigationBarHidden(true)
}

希望这有助于 查看实际情况,您可以查看这个开源应用程序(WIP)https://github.com/deepaksingh4/KidsBookApp

于 2021-03-30T18:40:21.087 回答
3

类似于@graycampbell 的答案,但更简单一些:

struct YourView: View {

    @State private var isNavigationBarHidden = true

    var body: some View {
        NavigationView {
            VStack {
                Text("This is the master view")
                NavigationLink("Details", destination: Text("These are the details"))
            }
                .navigationBarHidden(isNavigationBarHidden)
                .navigationBarTitle("Master")
                .onAppear {
                    self.isNavigationBarHidden = true
                }
                .onDisappear {
                    self.isNavigationBarHidden = false
                }
        }
    }
}

设置标题是必要的,因为它显示在您导航到的视图中的后退按钮旁边。

于 2019-12-27T16:57:28.350 回答
3

我尝试像这样在我的 Vstack 的大括号末尾添加 .navigationBarHidden(true)

NavigationView { Vstack(){"some Code"}.navigationBarHidden(true)}

并且导航栏消失了在此处输入图像描述,但是如果我像这样在导航栏的大括号末尾添加 .navigationBarHidden(true)

    NavigationView { Vstack(){"some Code"}}.navigationBarHidden(true)

导航栏不会消失在此处输入图像描述

于 2021-05-12T23:26:41.977 回答
2

⚠️你不需要设置标题。

NavigationView {
        
            VStack {
                Color.cyan
            }   
        
            .navigationBarHidden(true)
        
        }
    
        .navigationViewStyle(.stack)//⬅️
于 2022-02-05T05:28:18.543 回答
1

在用户登录后应显示 TabView 的应用程序上工作时,我遇到了类似的问题。

正如@graycampbell 在他的评论中所建议的那样,不应将 TabView 嵌入到 NavigationView 中,否则即使使用时也会出现“空白空间”.navigationBarHidden(true)

我用一个ZStack来隐藏 NavigationView。请注意,对于这个简单的示例,我使用@State@Binding来管理 UI 可见性,但您可能希望使用更复杂的东西,例如环境对象。

struct ContentView: View {

    @State var isHidden = false

    var body: some View {
        
        ZStack {
            if isHidden {
                DetailView(isHidden: self.$isHidden)
            } else {
                NavigationView {
                    Button("Log in"){
                        self.isHidden.toggle()
                    }
                    .navigationBarTitle("Login Page")
                }
            }
        }
    }
}

当我们按下 Log In 按钮时,初始页面消失,并加载了 DetailView。当我们切换注销按钮时,登录页面重新出现

struct DetailView: View {
    
    @Binding var isHidden: Bool
    
    var body: some View {
        TabView{
            NavigationView {
                Button("Log out"){
                    self.isHidden.toggle()
                }
                .navigationBarTitle("Home")
            }
            .tabItem {
                Image(systemName: "star")
                Text("One")
            }
        }
    }
}
于 2020-07-24T04:18:18.100 回答
1

我必须将 screen1 导航到 screen2。如果我将其用于 NavigationView,如上面的答案导航栏将被隐藏,但它的空间仍然存在(屏幕 1 中的空间量与高度)。

最后,我有自己的解决方案,可以在 NavigationView 内的任何视图中使用此代码,并且不关心 navigationBarTitle。像这样:

屏幕1:

NavigationView {
    SomeView {
        NavigationLink {
        // go to screen2
        }
    }.navigationBarHidden(true)
}

屏幕2:

NavigationView {
// some Views
}.navigationBarHidden(true)
于 2021-12-13T09:13:33.070 回答
1

我为此苦苦挣扎了一段时间,但最终对我有用的是......

ZStack {
    ...
}
.edgesIgnoringSafeArea(.all) //or .edgesIgnoringSafeArea(.top)
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)
于 2021-03-10T03:51:44.017 回答
0

同样的问题,我终于解决了。为了使导航完全消失,您需要将这些修饰符添加到其中的NavigationViewAND ALLNavigationsLinks中:

.navigationBarHidden(true)
.navigationBarTitleDisplayMode(.inline)

如果你不这样做也NavigationLinks不会工作。

于 2021-12-06T10:17:33.503 回答
-1

真的很喜欢@Vatsal Manot给出的想法,为此创建一个修饰符。
从他的答案中删除isHidden属性,因为我认为它没有用,因为修饰符名称本身暗示隐藏导航栏。

// Hide navigation bar.
public struct NavigationBarHider: ViewModifier {

    public func body(content: Content) -> some View {
        content
            .navigationBarTitle("")
            .navigationBarHidden(true)
    }
}

extension View {
    public func hideNavigationBar() -> some View {
        modifier(NavigationBarHider())
    }
}
于 2020-03-02T07:17:12.263 回答
-8

试着把NavigationView里面放一个GeometryReader.

GeometryReader {
    NavigationView {
        Text("Hello World!")
    }
}

NavigationView当它是根视图时,我经历了奇怪的行为。

于 2019-08-17T03:04:07.850 回答