skip to Main Content

The following is a simplified project to highlight the problem, which I have in a real project.

I have a project, where I add a SwiftUI view with UIHostingController, and the status bar at the top is transparent. I see it when I scroll the SwiftUI view.

It is easy to recreate, create a new iOS project with storyboard, and embed the ViewController in the storyboard with a NavigationView.

Then replace the ViewController content with this:

import UIKit
import SwiftUI

final class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let hostingController = UIHostingController(rootView: ScrollView { MySwiftUIView() })
        self.addChild(hostingController)
        view.addSubview(hostingController.view)
        hostingController.view.translatesAutoresizingMaskIntoConstraints = false
        hostingController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        hostingController.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        hostingController.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
        self.navigationController?.navigationBar.shadowImage = UIImage()
        self.navigationController?.navigationBar.backgroundColor = UIColor.yellow
        
        self.title = "MyTitle"
    }
}

struct MySwiftUIView: View {
    var body: some View {
        ZStack {
            Color.green
            ScrollView {
                VStack {
                    ForEach(0...100, id: .self) { index in
                        Text("This is line (index)")
                    }
                }
            }
        }
    }
}

The status bar is transparent, and shows the white background of the view:

Before scrolling

And when I start scrolling the MySwiftUIView, it is even more apparent that the status bar is transparent:

After scrolling

I have searched around to find a solution to this, because I want the status bar to have the same color as the navigation bar, and not showing content from the SwiftUI view in the status bar. But so far I haven’t found a solution.

2

Answers


  1. Try changing:

    hostingController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    

    to

    hostingController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
    

    I’m not 100% sure, it’s your expected result, but it does remove the SwiftUI content overlap.

    Login or Signup to reply.
  2. This is also a trick:

     func setStatusBar() {
            if #available(iOS 13, *)
            {
                let keyWindow = UIApplication.shared.connectedScenes
                        .filter({$0.activationState == .foregroundActive})
                        .compactMap({$0 as? UIWindowScene})
                        .first?.windows
                        .filter({$0.isKeyWindow}).first
                let statusBar = UIView(frame: (keyWindow?.windowScene?.statusBarManager?.statusBarFrame) ?? CGRect(x: 0, y: 0, width: screenWidth, height: statubarHeight))
                statusBar.backgroundColor = .green
                keyWindow?.addSubview(statusBar)
            } else {
                let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
                if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
                    statusBar.backgroundColor = .green
                }
                UIApplication.shared.statusBarStyle = .lightContent
            }
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search