Ios 如何删除SwiftUI NavigationView中的默认导航栏空间

Ios 如何删除SwiftUI NavigationView中的默认导航栏空间,ios,swift,swiftui-list,swiftui,Ios,Swift,Swiftui List,Swiftui,我不熟悉SwiftUI(和大多数人一样),正在尝试找出如何删除嵌入到NavigationView中的列表上方的一些空白 在此图像中,您可以看到列表上方有一些空白 我想做到的是 我试过使用 .navigationBarHidden(true) 但这并没有造成任何明显的变化 我目前正在这样设置navigiationView NavigationView { FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch

我不熟悉SwiftUI(和大多数人一样),正在尝试找出如何删除嵌入到NavigationView中的列表上方的一些空白

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

我想做到的是

我试过使用

.navigationBarHidden(true)
但这并没有造成任何明显的变化

我目前正在这样设置navigiationView

 NavigationView {
                FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
                    .navigationBarHidden(true)
                }
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: "")
}
}
NavigationView { Vstack(){"some Code"}.navigationBarHidden(true)}
    NavigationView { Vstack(){"some Code"}}.navigationBarHidden(true)
其中FileBrowserView是一个具有如下定义的列表和单元格的视图

 NavigationView {
                FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
                    .navigationBarHidden(true)
                }
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: "")
}
}
NavigationView { Vstack(){"some Code"}.navigationBarHidden(true)}
    NavigationView { Vstack(){"some Code"}}.navigationBarHidden(true)

我想指出的是,这里的最终目标是,您将能够单击这些单元格以深入到文件树中,从而在深入导航栏上显示“后退”按钮,但是我不希望在初始视图的顶部有任何内容。

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

如果不需要导航栏:

FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
如果需要大的导航栏(通常用于顶级视图):

如果需要标准(内联)导航栏(通常用于子标高视图):

希望这个答案能对你有所帮助


更多信息:

出于某种原因,SwiftUI要求您还为
.navigationBarHidden
设置
.navigationBarTitle
,以便正常工作

NavigationView{
FileBrowserView(jsonFromCall:URLRetrieve(URLtoFetch:applicationDelegate.apiURL))
.navigationBarTitle(“”)
.navigationBarHidden(真)
}

更新 正如@Peacemoon在评论中指出的,当您在导航堆栈中更深地导航时,导航栏将保持隐藏状态,无论您是否在后续视图中将
navigationBarHidden
设置为
false
。正如我在评论中所说的,这要么是由于苹果方面的执行不力,要么就是糟糕的文档(谁知道呢,也许有一种“正确”的方法来实现这一点)

不管是什么情况,我想出了一个解决办法,似乎可以产生原始海报所期望的效果。我不太愿意推荐它,因为它看起来不必要的黑,但是没有任何直接的隐藏和取消隐藏导航栏的方法,这是我能做的最好的了

此示例使用三个视图-
View1
具有隐藏的导航栏,
View2
View3
都具有带标题的可见导航栏

结构视图1:视图{ @状态变量isNavigationBarHidden:Bool=true var body:一些观点{ 导航视图{ ZStack{ 颜色:红色 导航链接(“视图2”,目的地:视图2(isNavigationBarHidden:self.$isNavigationBarHidden)) } .navigationBarTitle(“隐藏标题”) .navigationBarHidden(self.isNavigationBarHidden) 奥纳佩尔先生{ self.isNavigationBarHidden=true } } } } 结构视图2:视图{ @绑定变量isNavigationBarHidden:Bool var body:一些观点{ ZStack{ 颜色:绿色 NavigationLink(“视图3”,目的地:View3()) } .navigationBarTitle(“可见标题1”) 奥纳佩尔先生{ self.isNavigationBarHidden=false } } } 结构视图3:视图{ var body:一些观点{ 蓝色 .navigationBarTitle(“可见标题2”) } } 在导航堆栈中更深的视图上将
navigationBarHidden
设置为
false
,似乎无法正确覆盖最初将
navigationBarHidden
设置为
true
的视图的首选项,因此,我能想到的唯一解决办法是在将新视图推送到导航堆栈上时,使用绑定来更改原始视图的首选项


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

试着将
导航视图
放在
GeometryReader

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

NavigationView
是根视图时,我遇到了奇怪的行为。

这是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())
    }
}

与@graycampbell的答案类似,但更简单一点:

struct YourView:View{
@状态私有变量isNavigationBarHidden=true
var body:一些观点{
导航视图{
VStack{
文本(“这是主视图”)
NavigationLink(“详细信息”,目的地:文本(“这些是详细信息”))
}
.navigationBarHidden(isNavigationBarHidden)
.navigationBarTitle(“主控”)
奥纳佩尔先生{
self.isNavigationBarHidden=true
}
翁迪萨佩尔先生{
self.isNavigationBarHidden=false
}
}
}
}

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

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

extension View {
    func hideNavigationBar() -> some View {
        self
            .navigationBarTitle("", displayMode: .inline)
            .navigationBarHidden(true)
    }
}
struct SomeView: View {
    @EnvironmentObject var navBarPrefs: NavBarPreferences

    var body: some View {
        Text("Hello second screen")
        .onAppear {
            self.navBarPrefs.navBarIsHidden = false
        }
    } 
}
然后打电话,例如:

ZStack {
    *YOUR CONTENT*
}
.hideNavigationBar()

对我来说,我是将
.navigationBarTitle
应用于
导航视图
,而不是
列表
才是罪魁祸首。这在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)
        }
    }
}

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

非常喜欢@Vatsal Manot提出的为其创建修改器的想法。
从他的答案中删除
ishiden
属性,因为我觉得它没有用,因为修饰符名称本身暗示了这一点
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
            }
        }
    }
}
struct SomeView: View {
    @EnvironmentObject var navBarPrefs: NavBarPreferences

    var body: some View {
        Text("Hello second screen")
        .onAppear {
            self.navBarPrefs.navBarIsHidden = false
        }
    } 
}
struct SomeView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView().environmentObject(NavBarPreferences())
    }
}
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")
                }
            }
        }
    }
}
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")
            }
        }
    }
}
.navigationBarTitle("", displayMode: .inline)
init() {
    UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
    UINavigationBar.appearance().shadowImage = UIImage()
}
.navigationBarTitle("", displayMode: .automatic)
.navigationBarHidden(true) 
.navigationBarTitleDisplayMode(.inline)
ZStack {
    ...
}
.edgesIgnoringSafeArea(.all) //or .edgesIgnoringSafeArea(.top)
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)
NavigationView{...}.navigationBarTitle("", displayMode: .inline)
        .navigationBarHidden(true)
NavigationView{
InnerView{}.navigationBarTitle("", displayMode: .inline)
        .navigationBarHidden(true)
}
        .navigationBarBackButtonHidden(true)
        .navigationBarHidden(true)
        NavigationLink(
            destination: NextView()
                .navigationBarTitle("")
                .navigationBarHidden(true)
        ) {
            Text("NEXT VIEW")
        }
                    
NavigationView { Vstack(){"some Code"}.navigationBarHidden(true)}
    NavigationView { Vstack(){"some Code"}}.navigationBarHidden(true)