5

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.

enter image description here

  • Hey, @sohomang, before answering your question, let me ask what would you like to achieve? Maybe a colored background? Or maybe you want your views to start from the top and come down? – Mark Moeykens Oct 17 '19 at 21:02
  • @MarkMoeykens Both, actually! I'd like this NavigationView to have a fixed background color. Stacking `.background(myColor)` to the NavigationView didn't cut it. That's why I tried putting it on the VStack. –  Oct 18 '19 at 00:05
  • I'm having the very same issue, did you find any solution for that weird space in the top of a VStack inside NavigationView? – juliancadi Jan 21 '20 at 01:36

5 Answers5

5

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.
Nilay
  • 327
  • 3
  • 9
1

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.

superpuccio
  • 11,674
  • 8
  • 65
  • 93
0

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

Alex Stuckey
  • 1,250
  • 1
  • 14
  • 28
0

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)
    }
}
Payam Khaninejad
  • 7,692
  • 6
  • 45
  • 55
0

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)
}
Naveen Kumawat
  • 467
  • 5
  • 12