Remove White Space NavigationView? iOS Foundations M5 Wrap Up

Does anyone know how to remove the extra white space in a screen using a NavigationView as shown below? I tried a Spacer(), but that does not work…

Link to full repo code: GitHub - agholson/Video-List-App

My ContentView:

import SwiftUI

struct ContentView: View {
    
    // Inherits the VideoModel from the top-most view
    @EnvironmentObject var model: VideoModel
    
    var body: some View {
        
        NavigationView {
            VStack (alignment: .leading, spacing: 20) {
                Text("All Videos")
                    .font(.title)
                
                // MARK: - Video List
                ScrollView {
                    
                    LazyVStack(alignment: .leading) {
                        
                        // Loop through videos here 
                        ForEach(model.videos) { video in
                            
                            NavigationLink {
                                VideoView()
                                    .onAppear {
                                        model.setCurrentVideo(videoId: video.id)
                                    }
                            } label: {
                                Text(video.title)
                                    .padding(.bottom, 5)
                            }
                            .tint(.black)
                            
                            // Horizontal divider
                            Divider()

                        }
                        
                    }
                    
                }
                
                // Spacer to push everything up
                Spacer()
                
            }
            
        }
        .padding()
        .navigationViewStyle(.stack)
                
    }
}

That’s the navigation bar header. You can hide it by adding this code inside the NavigationView:

.navigationBarHidden(true)

You could also, instead of having Text("All Videos") in a VStack, just use the header as it’s meant to be used:

.navigationTitle(Text("All Videos"))

Hey @roosterboy thanks for giving this a shot!

Unfortunately, I tried that already, and it doesn’t work. Perhaps, it is something that has to do with iOS 13? Also, strangely, the .navigationTitle text does not display the title. Here’s how it looks with the suggested code:

Move the modifier .navigationTitle("All Videos") inside the NavigationView and attach it to the closing brace of the VStack.

Remove the modifier .navigationBarHidden(true).

In future it would be beneficial to post your code as text rather than a screenshot.

To format the code nicely, place 3 back-ticks ``` on the line above your code and 3 back-ticks ``` on the line below your code. The 3 back-ticks must be the ONLY characters on the line. The back-tick character is located on the same keyboard key as the tilde character ~ (which is located below the Esc key). You can also highlight an entire code block and click the </> button on the toolbar to wrap the block for you.

This also makes it easier for anyone assisting as they can copy the code and carry out some testing.

1 Like

Think of it this way: NavigationView is a container, the stack of Views that you are navigating through. Each View within that stack can have its own title and other properties. So, when you place a modifier like navigationTitle() or whatnot, it applies to the particular View inside the navigation stack, not the NavigationView itself.

1 Like

Hey @Chris_Parker and @roosterboy thanks for still taking shots at this!

Chris’s suggestion to move the .navigationTitle within the NavigationView as a modifier of the VStack made a big difference. It looks much better ascetically. However, is there any way to get rid of the last remaining white space, or would you all consider this normal?

Screenshot below shows latest changes with the .navigationTitle on the left, and old version with it outside on the right. Still, desired state would have even less white space, and make it aligned further on the left:

Here’s the latest ContentView:

//
//  ContentView.swift
//  AllVideosModule5WrapUp
//
//  Created by Shepherd on 11/6/21.
//

import SwiftUI

struct ContentView: View {
    
    // Inherits the VideoModel from the top-most view
    @EnvironmentObject var model: VideoModel
    
    // Tracks the text our user searches for
    @State private var searchText = ""
    
    var body: some View {
        
        NavigationView {
            VStack (alignment: .leading) {
                // MARK: - Video Title
//                Text("All Videos")
//                    .font(.title)
                
                // MARK: - Search Bar
                SearchView(searchString: $searchText)
                    .padding(.bottom)
                
                // MARK: - Video List
                ScrollView {
                    
                    LazyVStack(alignment: .leading) {
                        
                        // Loop through videos here 
                        ForEach(model.videos) { video in
                            
                            // If the search text is empty, then display everything
                            if searchText == "" {
                                // Displays the video with a title and divider line
                                VideoItemView(selectedVideo: video)
                            }
                            // Else if the video title contains the text searched for, then display it
                            else if video.title.contains(searchText) {
                                
                                VideoItemView(selectedVideo: video)
                            }

                        }
                        
                    }
                    
                }
                
                // Spacer to push everything up
                Spacer()
                
            }
                .navigationTitle("All Videos")
            
        }
            .padding()
            .navigationViewStyle(.stack)
//            .navigationBarHidden(true)
//            .navigationTitle(Text("All Videos"))

    }
}

See here for the GitHub repo as well

Chris, I didn’t include any more of the code, because to me the screenshot sufficed. It showed that the suggested modifiers did not change the behavior. I also posted the majority of the code in the original posting as well as link to the GitHub with all the codebase. I don’t like how the website here doesn’t show line numbers, so it’s harder to track. Also, the screenshot could show visually all of the code, while on a 13-inch Mac screen the code in the website besides a scrollable window. You can’t see all of it in one glimpse. However, I’ll post all the code in each posting for convenience for now on. Definitely easier grabbing it from here, versus clicking five different links to review in GitHub :slight_smile:

@roosterboy good to keep in mind all these views, and how they act as containers. I didn’t realize how it wouldn’t apply to the NavigationView itself, but rather the Views inside. That seems like a very important distinction.

Thanks for the help guys!!

The reason that you have more space on the left is because you have the .padding() modifier added to the bottom of the NavigationView.

To get a better result, remove that padding() modifier and add the modifier .padding(.horizontal) just after the closing brace of the VStack.

That will mean that the List view will have some padding on the leading and trailing edges without affecting the navigation title meaning that they will line up.

The reason that a NavigationView has some space at the top above the title is that there is room for navigation bar buttons to appear there if required.

1 Like

Hey Chris, that worked great, thanks! It all displays much better now. Now that I see it, it makes sense too, why the .padding(.horizontal) modifier helps so much here: it doesn’t place any top or bottom padding. It only places it, where needed on the sides, as you say on the leading and trailing edges.

Great tip about the NavigationView leaving some space at the top as well. I was able to get rid of it by replacing .navigationTitle with .navigationBarTitle as the modifier for the VStack. The .navigationBarTitle allows for an extra displayMode: .inline argument that removes the extra space. However, the text doesn’t look nearly as good as the regular title. So, I’ll likely switch back to the .navigationTitle modifier.

import SwiftUI

struct ContentView: View {
    
    // Inherits the VideoModel from the top-most view
    @EnvironmentObject var model: VideoModel
    
    // Tracks the text our user searches for
    @State private var searchText = ""
    
    var body: some View {
        
        NavigationView {
            VStack (alignment: .leading) {
                
                // MARK: - Search Bar
                SearchView(searchString: $searchText)
                    .padding(.bottom)
                
                // MARK: - Video List
                ScrollView {
                    
                    LazyVStack(alignment: .leading) {
                        
                        // Loop through videos here 
                        ForEach(model.videos) { video in
                            
                            // If the search text is empty, then display everything
                            if searchText == "" {
                                // Displays the video with a title and divider line
                                VideoItemView(selectedVideo: video)
                            }
                            // Else if the video title contains the text searched for, then display it
                            // Make them both lowercase so we ignore case
                            else if video.title.lowercased().contains(searchText.lowercased()) {
                                
                                VideoItemView(selectedVideo: video)
                            }

                        }
                        
                    }
                    
                }
                
                // Spacer to push everything up
                Spacer()
                
            }
                .padding(.horizontal)
            // Makes this the title of the current VStack
//                .navigationTitle("All Videos")
                .navigationBarTitle("All Videos", displayMode: .inline)
            
        }
            .navigationViewStyle(.stack)
//            .navigationBarHidden(true)
//            .navigationTitle(Text("All Videos"))

    }
}

You should also avoid navigationBarTitle(_:displayMode:) because it has been deprecated by Apple. You should use navigationTitle(_:) plus navigationBarTitleDisplayMode(_:) instead to achieve that effect.

1 Like

Hey thank you Patrick!

Much better to use the non-deprecated version. I didn’t realize that was even an option! I checked the documentation for .navigationTitle, and it only showed an argument as a String. I didn’t think to simply type .navigation.. to view the rest of the options.

Unfortunately, it makes it look as small as the photo above. I still haven’t figured out how to remove the extra white space for buttons that Chris mentioned.

Regardless, much better to include the non-deprecated version (always shocks me how many changes Apple makes to this language). Thanks!!