Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
SwiftUI Change Status Bar Color with UIWindow
//
// ContentView.swift
// StatusBarTest
//
// Created by hiroki on 2021/02/11.
//
import SwiftUI
struct ContentView: View {
@StateObject var statusBarConfigurator = StatusBarConfigurator()
var body: some View {
VStack(spacing: 30) {
Text("Status Bar Color Test")
.font(.title)
Button("Black") {
statusBarConfigurator.statusBarStyle = .darkContent
}
Button("White") {
statusBarConfigurator.statusBarStyle = .lightContent
}
}
.prepareStatusBarConfigurator(statusBarConfigurator) // UIWindowの用意
.frame(maxWidth: .infinity, maxHeight: .infinity) // 背景色をステータスバーまで広げるため
.background(Color.gray.ignoresSafeArea()) // ステータスバーの色をわかりやすくするために背景をグレーに
}
}
//
// StatusBarConfigurator.swift
// StatusBarTest
//
// Created by hiroki on 2021/02/11.
//
import UIKit
import SwiftUI
class StatusBarConfigurator: ObservableObject {
private var window: UIWindow?
var statusBarStyle: UIStatusBarStyle = .default {
didSet {
window?.rootViewController?.setNeedsStatusBarAppearanceUpdate()
}
}
fileprivate func prepare(scene: UIWindowScene) {
if window == nil {
let window = UIWindow(windowScene: scene)
let viewController = ViewController()
viewController.configurator = self
window.rootViewController = viewController
window.frame = UIScreen.main.bounds
window.alpha = 0
self.window = window
}
window?.windowLevel = .statusBar
window?.makeKeyAndVisible()
}
fileprivate class ViewController: UIViewController {
weak var configurator: StatusBarConfigurator!
override var preferredStatusBarStyle: UIStatusBarStyle { configurator.statusBarStyle }
}
}
fileprivate struct SceneFinder: UIViewRepresentable {
var getScene: ((UIWindowScene) -> ())?
func makeUIView(context: Context) -> View { View() }
func updateUIView(_ uiView: View, context: Context) { uiView.getScene = getScene }
class View: UIView {
var getScene: ((UIWindowScene) -> ())?
override func didMoveToWindow() {
if let scene = window?.windowScene {
getScene?(scene)
}
}
}
}
extension View {
func prepareStatusBarConfigurator(_ configurator: StatusBarConfigurator) -> some View {
return self.background(SceneFinder { scene in
configurator.prepare(scene: scene)
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment