Extra space in the Top of Detail View that won't go away (SwiftUI)

Viewed 5186

I have an extra space in a detail view that won't go away. The view comes from a NavigationLink but I've tried it with or without a NavigationView. I tried to wrap it replace the ScrollView with the NavigationView but that didn't work. I think a lot of Swift coders have encountered this problem and there's no proper answer out there that worked for me.

This is my DetailView

struct DetailView: View {
    var body: some View {
                
        ScrollView {
            VStack(alignment: .leading) {
                Text("Huge Font Recipe Title")
                .font(.system(size: 48, weight: .bold))
                .foregroundColor(.black)
                .padding([.leading, .top, .trailing])
                                            
                    VStack {
                        Image("img1")
                            .resizable()
                            .frame(width: 375, height: 375)
                            .aspectRatio(contentMode: .fit)
                            .frame(width: UIScreen.main.bounds.width)
                            
                        Spacer()

                            
                        }.padding(.bottom)
                                                        

                    }
                  }
               }
            
}
             
struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView()
    }
}

And this is the Parent view (Content View) which holds the NavigationView

import SwiftUI

struct ContentView: View {
    var body: some View {

        NavigationView {

            ScrollView (showsIndicators: false) {
                    VStack(spacing: 20) {
                        ForEach(recipecardData) { item in

                            NavigationLink(
                            destination: DetailView()) {

                            RecipeCards( card: item)
                        }
                    }
                }

                        }
        .navigationBarTitle("Navigation")
                    }
            }
}



            struct RecipeCards: View {

                var card: RecipeCard

                var body: some View {

                    ZStack {
                        Image(card.imageName)
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 334, height: 335)
                            .cornerRadius(10)
                            .padding()
                            .shadow(radius: 16)

                        Rectangle()
                            .foregroundColor(.clear)
                            .background(LinearGradient(gradient: Gradient(colors: [.red, .blue]), startPoint: .bottom, endPoint: .top)
            )
                            .frame(width: 334, height: 335)
                           .cornerRadius(10)


                        HStack {

                            Text(card.title)
                                .font(.system(size: 27,weight: .bold))
                                .foregroundColor(.white)
                                .frame(minWidth: 10, maxWidth: .infinity, alignment: .leading)
                                .lineLimit(2)
                                .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 20))

                            }

                        .padding(.bottom, 268)
                        .padding(EdgeInsets(top: 0, leading: 34, bottom: 0, trailing: 8))
                    }
                }
            }


            struct RecipeCard: Identifiable {
                var id = UUID()
                var title: String
                var imageName: String

            }

            let recipecardData =  [
            RecipeCard(title: "Title 1", imageName: "img1"),
            RecipeCard(title: "Title 2", imageName: "img2")
            ]


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
3 Answers

That is the NavigationBar with a large style. You can make it smaller by using this modifier:

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

Inline


Update due to OP's comment

If you want to keep the large title while expanding the contents, you should consider ignoring the safe area's top edge:

.edgesIgnoringSafeArea(.top)

Top

Also, you may want to add some paddings BEFORE ignoring safe area to preserve the inline navigation size.

Padding


Important

  1. Note that all of these modifiers should apply to the destination view.

  2. The NavigationBar will stay there and prevent touch events from passing to the views below. You should use .navigationBarHidden(true) if you really need to get rid of it.

You can set displayMode: .inline to the NavigationBar in your DetailView:

struct DetailView: View {
    var body: some View {
        ScrollView {
            ...
        }
        .navigationBarTitle("Some title", displayMode: .inline)
    }
}

In every step of navigation you can set a different NavigationBar title. By setting a displayMode you control its style (and height).

Your issue occurred because in your DetailView you set a large NavigationBar title (if you didn't specify it explicitly, its style will be copied from the parent view). Also, you didn't specify its text - it was empty.

Which means you didn't have an extra space between the NavigationBar and the title of your image. It was an empty large NavigationBar title.

Use .navigationBarTitleDisplayMode(.inline) in your DetailView instead of .navigationBarTitle(...) if no title needed for the detail view.

Related