iKK
iKK

Reputation: 7012

NavigationBar height for SwiftUI's NavigationLink DetailView in Portrait and Landscape

Using iOS14.5, Swift5.4, XCode12.5, and SwiftUI,

I am trying to build simple DetailView to which you can navigate to using a NavigationLink.

It all works, except that I have no idea about the height of my NavigationBar inside the DetailView. (note that I use the .inline Version by calling .navigationBarTitleDisplayMode(.inline) on the DetailView).

I am trying to show a simple two-line VStack in the DetailView.

And it turns out that the DetailView's body is covered by the NavigationBar unless I move the whole thing down by 56 Pixels (by using Spacer().frame(height: 56)).

And I don't even know the precise height of the NavigationBar And even worse, I don't know how to determine it dynamically for Portrait and Landscape rotations.

How do you make the DetailView's body start below the NavBar no matter rotation-states ?

Here example Screenshots for Portrait :

Left side: the title is cut off !           Right side: using a Spacer makes title appear

enter image description here

Here is how I open the navigationLink:

NavigationLink(
    destination: DetailView(session: session).navigationBarTitleDisplayMode(.inline),
    tag: session.id ?? "",
    selection: $selectedTag,
    label: { EmptyView() }
)

And here is the entire Detail-Screen:

(please notice the Spacer-distance of 56 in order to make the title visible at all)

import SwiftUI

struct DetailView: View {
    
    @State var session: THSession
    
    var body: some View {
        
        VStack(alignment: .leading) {
            
            Spacer().frame(height: 56)   // !!!!!!!!!! without this the title sits behind NavBar !!!!!!!!!!!!!!!!!!!
            
            Text(session.title)
                .font(.title)
                .fontWeight(.bold)
                .foregroundColor(.white)
            
            Spacer().frame(height: 16)
            
            HStack {
                Text(session.invitationCode)
                    .font(.title)
                    .fontWeight(.bold)
                    .foregroundColor(.white)
            }
            
            Spacer()
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
        .background(Color.red)
        .ignoresSafeArea()
    }
}

Upvotes: 2

Views: 8952

Answers (1)

jnpdx
jnpdx

Reputation: 52565

I'm assuming that you're using ignoresSafeArea() because you want the background to extend into the safe area. But, where you have it placed is having a side effect of making the titles extend into the nav bar area.

Instead, place ignoresSafeArea() inside the background modifier:

.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.background(Color.red.ignoresSafeArea())

Now, your titles won't extend into the safe area and you can avoid using a Spacer at the top of the View altogether.

Upvotes: 7

Related Questions