Search code examples
iosswiftuitransparentnavigationbar

Transparent navigationbar in SwiftUI with backgroundImage


enter image description here

I have a custom navigation bar that is the an image followed by the header text. The image is set to scale to fill but does not quite fill up the navigation bar. As such, you can see a little of the bar where the image does not cover. I've tried to set the background color of the nav bar to clear but that doesn't work. Any suggestions?

struct ContentView: View {
@State private var hideBar = true

var body: some View {
    VStack {
        NavigationView {
            ZStack {
                Image("bg5").resizable().scaledToFill()

                VStack {
                    NavigationLink(destination:
                    SubView(header: "Go to subview")) {
                        Text("Go to subview")
                    }.simultaneousGesture(TapGesture().onEnded {
                       self.hideBar = false     // << show, here to be smooth !!
                    })

                    NavigationLink(destination:
                        SubView(header: "Go again")) {
                        Text("Go to subview again")
                    }.simultaneousGesture(TapGesture().onEnded {
                       self.hideBar = false     // << show, here to be smooth !!
                    })
                }
                .navigationBarTitle("")
                .navigationBarHidden(hideBar)
                .onAppear {
                    self.hideBar = true  // << hide on back
                }
            }.edgesIgnoringSafeArea([.top, .bottom])
        }
    }
}
}

struct SubView: View {
var header: String
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

var btnBack : some View { Button(action: {
    self.presentationMode.wrappedValue.dismiss()
    }) {
        HStack {
                Image("subheaderback").resizable().scaledToFit()
                VStack(alignment: .center) {
                    Text(self.header)
                }.frame(width: 100, height: 100)
        }
    }.buttonStyle(PlainButtonStyle())
}

var body: some View {
    ZStack {
        Image("bg5").resizable().scaledToFill()
        VStack {
            Text("blah blah")

            Text("and more blah")
        }
    }.edgesIgnoringSafeArea([.top, .bottom])
    .navigationBarBackButtonHidden(true)
    .navigationBarItems(leading: btnBack)
}
}

extension UINavigationController {
override open func viewDidLoad() {
    super.viewDidLoad()

    let appearance = UINavigationBarAppearance()
    appearance.backgroundColor = .clear
    appearance.backgroundImage = UIImage(named: "subheader")

    navigationBar.standardAppearance = appearance
    navigationBar.compactAppearance = appearance
    navigationBar.scrollEdgeAppearance = appearance
}
}

Solution

  • Instead of setting background color you need different configuration, like below (tested with Xcode 11.4 / iOS 13.4)

    let appearance = UINavigationBarAppearance()
    appearance.configureWithTransparentBackground()            // << this one !!
    appearance.backgroundImage = UIImage(named: "subheader")
    // appearance.backgroundImageContentMode = .scaleAspectFit // if needed non-default