我是SwiftUI的新手(像大多数人一样),试图弄清楚如何删除我嵌入在NavigationView中的List上面的一些空白。

在此图像中,您可以看到列表上方有一些空白。

我想要完成的是:

我试过用:

.navigationBarHidden(true)

但这并没有带来任何明显的变化。

我现在像这样设置我的navigationview:

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

其中FileBrowserView是一个带有List和FileCells的视图,定义如下:

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: "")
    }
}

我想指出的是,这里的最终目标是,您将能够单击这些单元格来更深入地导航到文件树中,因此在更深入的导航中应该在栏上显示一个后退按钮,但在我的初始视图中,我不希望顶部出现这样的任何东西。


当前回答

视图修改器使它变得简单:

//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()
        }
    }
}

其他回答

视图修改器使它变得简单:

//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()
        }
    }
}

我必须从屏幕1导航到屏幕2。如果我像上面那样使用导航栏,导航栏将被隐藏,但它的空间仍然存在(高度的空间)在屏幕1中。

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

Screen1:

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

Screen2:

NavigationView {
// some Views
}.navigationBarHidden(true)

这是一个存在于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())
    }
}

把下面的代码放在你的NextView上

        .navigationBarBackButtonHidden(true)
        .navigationBarHidden(true)

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

        NavigationLink(
            destination: NextView()
                .navigationBarTitle("")
                .navigationBarHidden(true)
        ) {
            Text("NEXT VIEW")
        }
                    

出于某种原因,SwiftUI要求你也为. navigationbarhidden设置. navigationbartitle才能正常工作。

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

更新

正如@ peacmoonon在评论中指出的那样,当你在导航堆栈中导航时,导航栏仍然隐藏,不管你是否在后续视图中将navigationBarHidden设置为false。正如我在评论中所说,这要么是苹果执行不力的结果,要么只是糟糕的文档(谁知道呢,也许有一种“正确”的方法来实现这一点)。

无论如何,我想出了一个变通办法,似乎能产生原始海报想要的结果。我很犹豫要不要推荐它,因为它看起来没有必要那么俗气,但是没有任何直接的隐藏和取消隐藏导航栏的方法,这是我能做的最好的了。

这个例子使用了三个视图——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")
    }
}

在导航堆栈中更深的视图上设置navigationBarHidden为false似乎不能正确地覆盖最初将navigationBarHidden设置为true的视图的首选项,所以我能想到的唯一的解决方法是使用绑定来改变原始视图的首选项,当一个新视图被推到导航堆栈上时。

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