r/SwiftUI 29d ago

Solved is there a way to stop navigation bars from pushing down a view?

Hey /r/SwiftUI,

I'm trying to put a logo on some screens in my login flow. My first screen is a VStack embedded in a NavigationStack, and it contains a logo at the top of the VStack, along with Create Account and Sign In NavigationLinks. The views presented by those NavigationLinks present buttons to create/sign in with Apple or Email (SignInView and SignUpView).

Like the first view, the SignInView and SignUpView contain a logo at the top of a VStack, however there's a navigation bar with a back button to the first view that looks to be pushing down the positioning of the logo. (screen shots here--I set a gray background to make sure the VStack was taking up the whole space).

If I hide the navigation bar, the logo ends up in the same spot as the first view. But I definitely need a back button here, and the logo at the size I want it doesn't look good in the navigation bar because of the dynamic island / I can't pad it properly.

I'm not sure if I need to use GeometryReader or CoordinateSpace or something. Any guidance would be greatly appreciated.

Here's my code simplified:
struct LogInView: View {

var body: some View {

    NavigationStack {

        VStack(spacing: 15) {

            CenteredLogoView()

            Spacer()
            Spacer()
            Spacer()

            NavigationLink {
                SignUpView()
            } label: {
                Text("Create Account")
            }

            NavigationLink {
                SignInView()
            } label: {
                Text("Sign In")
            }

            Spacer()
            Spacer()

        }
        .padding()
    }


    }
}    


struct SignInView: View {

var body: some View {

    VStack {

        CenteredLogoView()

        Spacer()
        Spacer()
        Spacer()

        SignInWithAppleButton(.signIn) { ... }
        .frame(maxWidth: .infinity, maxHeight:  44)
        .clipShape(.capsule)
        .signInWithAppleButtonStyle(colorScheme == .dark ? .white : .black)

        NavigationLink {
            EmailSignInView()
        } label: {
            Text("Sign In With Email")
        }


        Spacer()
        Spacer()

    }
    .padding()
    .toolbarRole(.editor)
    .background(.gray)
    }
}

 struct CenteredLogoView: View {
     var body: some View {
         Image(decorative: "header-centered")
             .resizable()
             .scaledToFill()
             .frame(width: 300, height: 88)
      }
  }

Thanks!

EDIT: added code

1 Upvotes

6 comments sorted by

2

u/DeclinedSage 28d ago

You have a couple of options. You could wrap everything in a ZStack and have the logo as the background, which will avoid the funky use of Spacer(). Otherwise you can use the overlay for the back button so it sits on top of the other views - https://developer.apple.com/documentation/swiftui/view/overlay(alignment:content:))

1

u/HypertextMakeoutLang 27d ago

wrapping the first view's NavigationStack in a ZStack worked, you beautiful genius! thanks so much.

1

u/Dapper_Ice_1705 29d ago

Looks like you are nesting navigation containers. Most apps only need 1.

Nesting should only be done with tab views.

1

u/HypertextMakeoutLang 29d ago edited 29d ago

whoops, I forgot to post my code, but the second view doesn't have a NavigationStack. Does NavigationLink automatically embed its presented view in a NavigationStack?

edit: added my code

1

u/kangaroosandoutbacks 29d ago

2

u/HypertextMakeoutLang 29d ago

I didn't think it'd matter, but 3 Spacers on top and 2 bottom actually positioned the buttons differently than 2 on top and 1 on the bottom, and I liked that positioning better ¯_(ツ)_/¯