Search code examples
swiftuiswiftui-navigationviewswiftui-navigationstack

How to center views vertically as if there were no navigation title?


I have a NavigationStack/NavigationView which loads its links. When it's loading or contains no links, I want to display a view centered in the screen to inform the user.

However, when there's a navigation title (.navigationTitle()), it takes space from the other views and centers the remaining content lower on the screen than the true center (and I think it looks more correct in the true center).

Is there a way to have the views ignore the navigation title and center in the true center?

I tried nesting everything in a GeometryReader and using proxy.size.height / 2 as the y position, but this still doesn't fix it. The only fix I did find was using proxy.size.height / 2 - geo.safeAreaInsets.top - geo.safeAreaInsets.bottom, but this seems hacky, and I'm wondering if there's a better solution.

Image references: Without title vs with title

var body: some View {
    NavigationStack {
        ProgressView()
            .controlSize(.large)
            .navigationTitle("Feed") // only difference
    }
}

Solution

  • One way to fix this is by overlaying the ProgressView on the NavigationStack.

    struct TestView: View {
        @State var feed: String? = nil
    
        var body: some View {
            NavigationStack {
                VStack {
                    if let feed {
                        Text(feed)
                    }
                    Spacer()
                }
                .navigationTitle("Feed")
            }
            .overlay {
                if feed == nil {
                    ProgressView()
                        .controlSize(.large)
                }
            }
            .task {
                try? await Task.sleep(for: .seconds(2))
                feed = "Here's the deets."
            }
        }
    }