Status Bar Background Color in SwiftUI

In iOS 15 it looks like the status bar default is now to have a transparent background. If you don't like this here is how you can change it.

Overview

With the status bar now having a default transparent background in iOS 15, your application might look odd. These types of changes are going to happen as apple evolves the UI, but it would be nice to know how do I change it back to an opaque background.

SwiftUI and ViewModifiers

This is one solution to the problem. If you are building an application in SwiftUI and just need to have it work for a single screen where you might have some content scrolling underneath then you do the following.

Steps

• Build a ViewModifier with some attributes.
• Assign it to the view you want to modify
• Done

Create the ViewModifier

The following code shows you how the ViewModifer can be constructed with some initial properties for backgroundColor and textColor. We are creating this ViewModifier as a reusable modifier that you can apply to any view.


struct NavigationBarModifier: ViewModifier {
    
  var backgroundColor: UIColor
  var textColor: UIColor

  init(backgroundColor: UIColor, textColor: UIColor) {
    // assign
    self.backgroundColor = backgroundColor
    self.textColor = textColor
    // configure
    let coloredAppearance = UINavigationBarAppearance()
    coloredAppearance.configureWithTransparentBackground()
    coloredAppearance.backgroundColor = .clear
    coloredAppearance.titleTextAttributes = [.foregroundColor: textColor] 
    coloredAppearance.largeTitleTextAttributes = [.foregroundColor: textColor]
    // change appearance
    UINavigationBar.appearance().standardAppearance = coloredAppearance
    UINavigationBar.appearance().compactAppearance = coloredAppearance
    UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
    UINavigationBar.appearance().tintColor = textColor
  }

  func body(content: Content) -> some View {
    ZStack{
       content
        VStack {
          GeometryReader { geometry in
              Color(backgroundColor) // This is Color so we can reference frame
                .frame(height: geometry.safeAreaInsets.top)
                .edgesIgnoringSafeArea(.top)
              Spacer()
          }
        }
     }
  }
    
}

Applying the ViewModifier

Go to your main view or any view that you want to modify and try it out. Created a property called statusBarModifier and assigned the background color and text color. Then I wrapped a VStack within the body of my view and assigned a .modifier where I passed in the statusBarModifier we created. The status bar background color should be red and the text color should be white in your preview.

struct ContentView: View {
    
    let statusBarModifier = NavigationBarModifier(backgroundColor: .red, textColor: .white)
    
    var body: some View {
        VStack(spacing: 0) {
            Text("Hello, world!")
                .padding()
        }.modifier(statusBarModifier)
        
    }
}

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

Conclusion.

I don’t know if this is the ideal solution. In my situation I only had a 2 screens that needed to be modified. The source material for this post came from this article. If you go to that article you can get additional instructions on you can extend this view and apply it globally to all your views.