swiftuiswiftui-navigationviewswiftui-navigationstack

adding .navigationTitle() adds unwanted padding to destination view


When I add a .navigationTitle() modifier to a parent view, I notice that extra padding is added to the top of the child view. This seems somewhat unexpected, as adding the navigation title doesn't add any navigation items to the child view: in both cases, the only navigation item in the child view is the back link.

Is there a way I could avoid the extra padding in the child view, while still using .navigationTitle()?

The example below demonstrates this behavior (if you comment out the .navigationTitle() modifier you will notice the top padding on the child view decrease).

Parent View:

struct ContentView: View {
  @State var navigationPath: [String] = []

  var body: some View {
    NavigationStack(path: $navigationPath) {
      VStack {
        Button(action: {navigationPath.append("View2")}){
          Text("Tap Me!")
            .font(.title)
        }
        .navigationDestination(for: String.self) { _ in
          SecondView()
        }
      }
      .navigationTitle("First View")
    }
  }
}

#Preview {
    ContentView()
}

Child View:

struct SecondView: View {
  var body: some View {
    VStack {
      Divider()
      Text("The Second View")
        .font(.title)
      Divider()
      Spacer()
    }
  }
}

#Preview {
  SecondView()
}

Please note, the issue persists if NavigationView and NavigationLink are used instead of NavgiationStack.


Solution

  • That's because your first view has a large navigation title and your second view has none.

    You have at least two choices:

    1. Set a (large) navigation title to your second view also:
    struct NavigationTitlePaddingSecondView: View {
        var body: some View {
            VStack {
                Divider()
                Text("The Second View")
                    .font(.title)
                Divider()
                Spacer()
                    .navigationTitle("Second View")
            }
        }
    }
    
    1. Or, specify that your second view should have a smaller navigation title mode:
    struct NavigationTitlePaddingSecondView: View {
        var body: some View {
            VStack {
                Divider()
                Text("The Second View")
                    .font(.title)
                Divider()
                Spacer()
                    // .navigationTitle("Second View")
                    .toolbarTitleDisplayMode(.inline)
            }
        }
    }
    

    You can obviously also set a title for the second view, or change the title mode for the first view to smaller (.inline).