ios - 如何在 SwiftUI 应用程序生命周期中更改 StatusBarStyle?

标签 ios swift colors swiftui statusbar

我已经花了很多时间试图找出一种使用新生命周期将 statusBarStyle 更改为亮/暗的方法 SwiftUI 应用程序 .
关于状态栏的最新帖子教如何隐藏它,但我不想这样做,我只需将其更改为深色或浅色。
要更改颜色,我发现的最新方法是打开 SceneDelegate.swift 并更改 window.rootViewController 以使用我自己的 HostingController,但它仅适用于使用 的项目UIKit 应用委托(delegate)生命周期 .使用 SwiftUI 应用生命周期 , SceneDelegate.swift 不会生成,请问在哪里可以生成呢?
我可以通过 Xcode 界面上的常规设置来完成。我的问题是关于如何通过代码动态地做到这一点。

  • 目标:iOS 14
  • IDE:Xcode 12 beta 3
  • 操作系统:MacOS 11 Big Sur

  • 以下是我到目前为止所得到的。
    Everything.swift
    import Foundation
    import SwiftUI
    
    class LocalStatusBarStyle { // style proxy to be stored in Environment
        fileprivate var getter: () -> UIStatusBarStyle = { .default }
        fileprivate var setter: (UIStatusBarStyle) -> Void = {_ in}
    
        var currentStyle: UIStatusBarStyle {
            get { self.getter() }
            set { self.setter(newValue) }
        }
    }
    
    struct LocalStatusBarStyleKey: EnvironmentKey {
        static let defaultValue: LocalStatusBarStyle = LocalStatusBarStyle()
    }
    
    extension EnvironmentValues { // Environment key path variable
        var localStatusBarStyle: LocalStatusBarStyle {
            get {
                return self[LocalStatusBarStyleKey.self]
            }
        }
    }
    
    class MyHostingController<Content>: UIHostingController<Content> where Content:View {
        private var internalStyle = UIStatusBarStyle.default
    
        @objc override dynamic open var preferredStatusBarStyle: UIStatusBarStyle {
            get {
                internalStyle
            }
            set {
                internalStyle = newValue
                self.setNeedsStatusBarAppearanceUpdate()
            }
        }
        
        override init(rootView: Content) {
            super.init(rootView:rootView)
    
            LocalStatusBarStyleKey.defaultValue.getter = { self.preferredStatusBarStyle }
            LocalStatusBarStyleKey.defaultValue.setter = { self.preferredStatusBarStyle = $0 }
        }
    
        @objc required dynamic init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    }
    
    struct TitlePage: View {
        @Environment(\.localStatusBarStyle) var statusBarStyle
        @State var title: String
    
        var body: some View {
            Text(title).onTapGesture {
                if self.statusBarStyle.currentStyle == .darkContent {
                    self.statusBarStyle.currentStyle = .default
                    self.title = "isDefault"
                } else {
                    self.statusBarStyle.currentStyle = .darkContent
                    self.title = "isDark"
                }
            }
        }
    }
    
    struct ContainerView: View {
        var controllers: [MyHostingController<TitlePage>]
        
        init(_ titles: [String]) {
            self.controllers = titles.map { MyHostingController(rootView: TitlePage(title: $0)) }
        }
        
        var body: some View {
            PageViewController(controllers: self.controllers)
        }
    }
    
    struct PageViewController: UIViewControllerRepresentable {
        var controllers: [UIViewController]
        
        func makeUIViewController(context: Context) -> UIPageViewController {
            let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
            return pageViewController
        }
        
        func updateUIViewController(_ uiViewController: UIPageViewController, context: Context) {
            uiViewController.setViewControllers([controllers[0]], direction: .forward, animated: true)
        }
        
        typealias UIViewControllerType = UIPageViewController
    }
    
    MyApp.swift
    import SwiftUI
    
    @main
    struct TestAppApp: App {
        var body: some Scene {
            WindowGroup {
                ContainerView(["Subscribe", "Comment"])
            }
        }
    }
    
    struct TestAppApp_Previews: PreviewProvider {
        static var previews: some View {
            Text("Hello, World!")
        }
    }
    
    enter image description here

    最佳答案

    向 Info.plist 添加两个值:

    <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
    <key>UIStatusBarStyle</key>
    <string>UIStatusBarStyleLightContent</string>
    
    这适用于新的 SwiftUI 应用程序生命周期 (@main)。在 iOS14.4 上验证。
    enter image description here

    关于ios - 如何在 SwiftUI 应用程序生命周期中更改 StatusBarStyle?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63093040/

    相关文章:

    android - 如何在android中的图像的触摸部分执行颜色混合

    iphone - UIBarButtonSystemItem PageCurl 不随工具栏改变颜色

    python - 无需导入非标准库即可查找给定位置的像素颜色

    ios - 什么被弃用了?如何在所有版本中处理它?

    ios - 单击 UIImageView SWIFT 不工作

    objective-c - 如何用Cocos2D(iOS)创建多关卡游戏?

    ios - 我想在单个 TableView 中使用 nib 中的两个不同的自定义单元格。两个原型(prototype)电池具有不同的高度

    ios - swift:tableView中的图像

    ios - 如何按内部子项对 Firebase 快照进行排序

    ios - 如何使用来自 API 的数据搜索 tableview?