Home > Mobile >  Navigation bar only have background when scroll
Navigation bar only have background when scroll

Time:04-14

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

CodePudding user response:

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

use this code in viewWillAppear

CodePudding user response:

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)

CodePudding user response:

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.

  • Related