skip to Main Content

I am trying to implement a detail view which is linked from a navigation view.
In this detail view, there is a default nav bar on top with a back button.
But the bar only show some color when I scroll up. I have no idea why.

No Scroll: Transparent Nav Bar

Scroll: Have Background Color

Initially, the nav bar doesn’t have background either when it’s scrolling or not.
So I created an init() method for setting up the style.

 init(fruit: Fruit) {
    self.fruit = fruit
    if #available(iOS 15.0, *) {
        let navigationBarAppearance = UINavigationBarAppearance()
        navigationBarAppearance.configureWithDefaultBackground()
        
        UINavigationBar.appearance().standardAppearance = navigationBarAppearance
        UINavigationBar.appearance().compactAppearance = navigationBarAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance
    }
  }

The Body View is a Navigation View on the outside and scroll view inside.
** For anyone wonder why I set the navbar to hidden in the VStack, is because if I don’t hide it, there would be some huge space above the image. (I have no idea why)
Huge Space, no idea what caused it

** Updated Code **
I updated my code which use the Opaque background.
But it seems like none of those config are visible.

init(fruit: Fruit) {
    self.fruit = fruit
    let navBarAppearance = UINavigationBarAppearance()
    navBarAppearance.configureWithOpaqueBackground()
    UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
    UINavigationBar.appearance().standardAppearance = navBarAppearance
}

var body: some View {
    NavigationView {
        ScrollView(.vertical, showsIndicators: false) {
            VStack(alignment: .center, spacing: 20) {
                // HEADER
                FruitHeaderView(fruit: fruit)
                
                VStack(alignment: .leading, spacing: 20) {
                    // TITLE
                    Text(fruit.title)
                        .font(.largeTitle)
                        .fontWeight(.heavy)
                        .foregroundColor(fruit.gradientColors[1])
                    
                    
                } //: VSTACK
                .padding(.horizontal, 20)
                .frame(maxWidth: 640, alignment: .center)
            } //: VSTACK
            .navigationBarHidden(true)
        } //: SCROLL
        .edgesIgnoringSafeArea(.top)
    } //: NAVIGATION
    .navigationBarTitle(fruit.title, displayMode: .inline)
    .navigationViewStyle(StackNavigationViewStyle())
}

Config the nav bar during init, but still don't see the background until I scroll

*** Solution ***
It turns out I have to put the configurations code of the nav bar in the parent view. During init().
Can anyone explain why this on the parent view? Or if I want different style in parent and child what should I do?

    init() {
        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
         UINavigationBar.appearance().standardAppearance = navBarAppearance
    }

var body: some View {
    NavigationView {
        List {
            ForEach(fruits.shuffled()) { item in
                NavigationLink {
                    FruitDetailView(fruit: item)
                } label: {
                    FruitRowView(fruit: item)
                        .padding(.vertical, 4)
                }
            }
        }
        .listStyle(.plain)
        .navigationTitle("Fruits")
    } //: NAVIGATION

}

Parent View

5

Answers


  1.         navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
            navigationController?.navigationBar.shadowImage = UIImage()
    

    use this code in viewWillAppear

    Login or Signup to reply.
  2. Use my extension:

    extension UIViewController {
    func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
    if #available(iOS 13.0, *) {
    let navBarAppearance = UINavigationBarAppearance()
    navBarAppearance.configureWithOpaqueBackground()
    navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
    navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
    navBarAppearance.backgroundColor = backgoundColor
    navigationController?.navigationBar.standardAppearance = navBarAppearance
    navigationController?.navigationBar.compactAppearance = navBarAppearance
    navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
    
    navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
    navigationController?.navigationBar.isTranslucent = false
    navigationController?.navigationBar.tintColor = tintColor
    navigationItem.title = title
    
    } else {
    // Fallback on earlier versions
    navigationController?.navigationBar.barTintColor = backgoundColor
    navigationController?.navigationBar.tintColor = tintColor
    navigationController?.navigationBar.isTranslucent = false
    navigationItem.title = title
      }
     }
    }
    

    call it in viewDidAppear or viewDidLoad , in your case set background to clear… How to use:

    configureNavigationBar(largeTitleColor: .yourColor, backgoundColor: .yourColor, tintColor: .yourColor, title: "YourTitle", preferredLargeTitle: false)
    
    Login or Signup to reply.
  3. You need opaque appearance, because default one means system-selected-by-design which is changed from version to version.

    demo

        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
    

    Tested with Xcode 13.3 / iOS 15.4 (in ContentView.init)

    Note: onAppear is too late to inject above code, the appearance settings are applied on objects created after it, and onAppear is called after NavigationView created. So use it either in init, or anywhere else, but before view created.

    Login or Signup to reply.
  4. This worked for me –

    func changeNavBar(navigationBar: UINavigationBar, to color: UIColor) {
                let appearance = UINavigationBarAppearance()
                appearance.configureWithOpaqueBackground()
                appearance.backgroundColor = color
                navigationBar.standardAppearance = appearance;
                navigationBar.scrollEdgeAppearance = navigationBar.standardAppearance
    }
    
    Login or Signup to reply.
  5. In Xcode 14.3 the solutions above did not work but the following approach proved to be successful and resolved the issue for me.

    struct MyApp: App { /../ }
    extension UINavigationController {
        override open func viewWillLayoutSubviews() {
            let transparentAppearance = UINavigationBarAppearance()
            transparentAppearance.configureWithTransparentBackground()
            transparentAppearance.backgroundColor = .clear
            transparentAppearance.shadowColor = .clear
            navigationBar.standardAppearance = transparentAppearance
            navigationBar.compactAppearance = transparentAppearance
            navigationBar.scrollEdgeAppearance = transparentAppearance
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search