0

I'm experiencing an issue with the NavigationBar in SwiftUI where it doesn't animate when Detail View is pushed and there is no or empty [navigation] title in the root view of a NavigationStack.

Here is an example that reproduces the issue:

//
//  ContentView.swift
//  iTestNavStackFresh
//
//  Created by Aleksandar Petrov on 6.04.23.
//

import SwiftUI

enum NavigationRoute {

    case details
}

struct ContentView: View {

    @State private var navigationPath = NavigationPath()

    var body: some View {
        NavigationStack(path: $navigationPath) {
            Button("Go to Details View") {
                navigationPath.append(NavigationRoute.details)
            }
//            .navigationTitle("ANY NON EMPTY TITLE WILL DO") // <-- Uncomment to fix the issue
//            .navigationBarTitleDisplayMode(.inline)
            .navigationDestination(for: NavigationRoute.self) { navigationRoute in
                switch navigationRoute {
                case .details:
                    DetailView()
                        .toolbarBackground(Color.white, for: .navigationBar)
                        .toolbarBackground(.visible, for: .navigationBar)
                }
            }
        }
    }
}

struct DetailView: View {

    var body: some View {
        Text("Detail View")
            .font(.title)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(
                Color.black
                    .opacity(0.3)
            )
            .navigationTitle("Detail View")
            .navigationBarTitleDisplayMode(.inline)
    }
}


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

Edit:

Tested on iPhone 11 Pro (iOS 16.4) and iPhone 12 (iOS 16.1.1)

Edit 2:

NavigationView works as expected

//
//  ContentView.swift
//  iTestNavStackFresh
//
//  Created by Aleksandar Petrov on 6.04.23.
//

import SwiftUI

struct ContentView: View {

    var body: some View {
        NavigationView {
            NavigationLink(
                destination: DetailView()
                    .toolbarBackground(Color.white, for: .navigationBar)
                    .toolbarBackground(.visible, for: .navigationBar)
            ) {
                Text("Hello, World!")
            }
        }
    }
}

struct DetailView: View {

    var body: some View {
        Text("Detail View")
            .navigationTitle("Detail View")
            .navigationBarTitleDisplayMode(.inline)
            .font(.title)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(
                Color.black
                    .opacity(0.3)
            )
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
apetrov
  • 430
  • 5
  • 16
  • Your example animates just fine for me. Have you tested on a real device? Might be the simulator playing tricks with you – bjorn.lau Apr 06 '23 at 13:41
  • I'm testing with real device - iPhone 11 Pro with iOS 16.4 – apetrov Apr 06 '23 at 14:02
  • What part of the animation is not working? – bjorn.lau Apr 06 '23 at 14:04
  • Just the navigation bar (title). When DetailView is pushed, navigation bar is immediately shown, while the content is animated – apetrov Apr 06 '23 at 14:17
  • I don't think this is a bug. This is how iOS does it. Either you navigate from a navigation bar that is already there, or it will appear like that. – bjorn.lau Apr 06 '23 at 14:37
  • I've tested with `NavigationView` and it works as expected. Edited my question with example code. – apetrov Apr 06 '23 at 15:00
  • 1
    @bjorn.lau I found a workaround (posted it as answer). I appreciate you taking the time to answer my question. – apetrov Apr 06 '23 at 15:13

1 Answers1

0

The following code solves my problem

//
//  ContentView.swift
//  iTestNavStackFresh
//
//  Created by Aleksandar Petrov on 6.04.23.
//

import SwiftUI

enum NavigationRoute {

    case details
}

struct ContentView: View {

    @State private var navigationPath = NavigationPath()
    @State private var isNavigationBarHidden: Bool = true

    var body: some View {
        NavigationStack(path: $navigationPath) {
            Button("Go to Details View") {
                navigationPath.append(NavigationRoute.details)
            }
            // >>> EMPTY TITLE BUT ANIMATION WORKS
            .navigationTitle("") // this sets the Back button text when a new screen is pushed
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .principal) {
                    Text("") // this sets the screen title in the navigation bar, when the screen is visible
                }
            }
            .navigationBarTitleDisplayMode(.inline)
            // ===
            .navigationDestination(for: NavigationRoute.self) { navigationRoute in
                switch navigationRoute {
                case .details:
                    DetailView()
                        .toolbarBackground(Color.white, for: .navigationBar)
                        .toolbarBackground(.visible, for: .navigationBar)
                }
            }
        }
    }
}

struct DetailView: View {

    var body: some View {
        Text("Detail View")
            .navigationTitle("Detail View")
            .navigationBarTitleDisplayMode(.inline)
            .font(.title)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(
                Color.black
                    .opacity(0.3)
            )
    }
}


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

apetrov
  • 430
  • 5
  • 16