简体   繁体   中英

SwiftUI - VStack not filling entire screen when placed in NavigationView

It seems like when placed in a NavigationView, VStacks won't fill the entire vertical space. Or maybe I'm doing something wrong?

var body: some View {
    NavigationView {
        VStack(alignment: .leading) {
            Text("HEY")
        }
        .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        .background(.gray)
    }
    .navigationBarTitle("Reçu", displayMode: .inline)
}

I also customized UINavigationBar to give it some color and set navigationBarTitle to inline.

I tried 2 workarounds:

  • .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: Alignment.topLeading)
  • .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)

The first one fills more vertical space, but not all of it.

在此处输入图像描述

It looks like there are two navigation views added to your view hierarchy.

  • If the parent view has a NavigationView and you are going into child view using NavigationLink then you don't have to add a NavigationView to your child view it has automatically added.
  • If you are directly setting new rootView for your UIHostingController then add NavigationView into that new rootView .

In order to have a background color for your view I suggest you go for the ZStack view:

struct ContentView: View {
    var body: some View {
        NavigationView {
            ZStack {
                Color.gray                
            }
            .edgesIgnoringSafeArea(.all)
            .navigationBarTitle("Reçu", displayMode: .inline)
        }
    }
}

You can even create you custom view (to reuse wherever you want) that takes a colour as a parameter:

struct BgColorView<Content>: View where Content: View{
    private let color: Color
    private let content: () -> Content

    init(color: Color, @ViewBuilder content: @escaping () -> Content) {
        self.color = color
        self.content = content
    }
    var body: some View {
        ZStack {
            color.edgesIgnoringSafeArea(.all)
            content()
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            BgColorView(color: Color.green) {
                Text("Hello world!")
            }
            .navigationBarTitle("Reçu", displayMode: .inline)
        }
    }
} 

For the second issue, it strictly depends on your needs. The easiest way to have content aligned top-left is using the Spacer view.

struct ContentView: View {
    var body: some View {
        NavigationView {
            BgColorView(color: Color.green) {
                VStack {
                    HStack {
                        Text("Hello world!")
                        Spacer()
                    }
                    Spacer()
                }
            }
            .navigationBarTitle("Reçu", displayMode: .inline)
        }
    }
}

But again, it depends on what you're trying yo get.

It looks like you're currently setting the navigationBarTitle of your NavigationView . However, if you remove the navigationBarTitle on the list that might remove the space you're trying to clean up. See this other stack overflow answer on how to do that: How to remove the default Navigation Bar space in SwiftUI NavigiationView

This is Apple's official tutorial, where they also put the navigationBarTitle on the List instead of the actual NavigationView : https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation#set-up-navigation-between-list-and-detail

This is a sample that shows you how to switch a custom view or screen:

struct MyView: View {
    @State var isActive = false
    var body: some View {
        NavigationView {
                VStack(alignment: .leading) {
                    Button(action: {
                        self.isActive = true
                    }) {
                        Text("Hey")
                    }
                }
                .frame(width: 100, height: 100, alignment: .center)
                .background(Color.blue)
                .foregroundColor(Color.white)
            }
        .fullScreenCover(isPresented: self.$isActive, content: {
            Text("This is full screen View or custom view")
        })
            .navigationBarTitle("Reçu", displayMode: .inline)
    }
}

First of all thank you Niley for pointing the issue, but there is one case missing: What if I want a new NavigationView in ChildNavigation View? The answer is just to add these three lines in content view of navigation view:

.navigationBarTitle(Text(""), displayMode: .inline)

.navigationBarHidden(true)

.navigationBarBackButtonHidden(true)

NavigationView{
    VStack{} or HStack{} or ZStack{}
    .navigationBarTitle(Text(""), displayMode: .inline)
    .navigationBarHidden(true)
    .navigationBarBackButtonHidden(true)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM