SwiftUI:为特定视图设置状态栏颜色

Posted

技术标签:

【中文标题】SwiftUI:为特定视图设置状态栏颜色【英文标题】:SwiftUI: Set Status Bar Color For a Specific View 【发布时间】:2020-04-21 11:34:33 【问题描述】:

我一直在尝试为我的应用程序设置一个视图的状态栏颜色。

我已经尝试过此处列出的解决方案..'How to change Status Bar text color in ios',但这为整个应用程序设置了它。

我想要的是状态栏颜色为在 SceneDelegate.swift 中设置的 rootViewController 设置白色文本,然后为所有其他视图默认设置(根据暗模式从白色变为黑色)。

有什么想法吗?

【问题讨论】:

【参考方案1】:

状态栏内容的颜色可以根据每个视图控制器进行修改,但 SwiftUI 通常只使用一个视图控制器,即根托管视图控制器。所以它需要推动那个根控制器来改变preferredStatusBarStyle 属性,它在基类中是只读的。

所以我们的想法是覆盖默认的 UIHostingController 以有可能更改 preferredStatusBarStyle 的值并使用自定义的 Environment 值,以便任何内部 SwiftUI 子视图都可以修改首选的内容样式。

这里是方法,scratch,(假设目标Info.plist配置正确)

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) 
    


// Custom Environment key, as it is set once, it can be accessed from anywhere
// of SwiftUI view hierarchy
struct LocalStatusBarStyleKey: EnvironmentKey  
    static let defaultValue: LocalStatusBarStyle = LocalStatusBarStyle()


extension EnvironmentValues  // Environment key path variable
    var localStatusBarStyle: LocalStatusBarStyle 
        get 
            return self[LocalStatusBarStyleKey.self]
        
    


// Custom hosting controller that update status bar style
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)
    

用法..

1) 场景委托中的某处

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) 
        ...
        window.rootViewController = MyHostingController(rootView: contentView)

2) 内容视图中的某处

struct ContentView: View 
    @Environment(\.localStatusBarStyle) var statusBarStyle

    ...
    var body: some View 
        ZStack 
           ....
            NavigationView 
                NavigationLink(destination:  ...) 
                    ...
                
                .onAppear 
                    self.statusBarStyle.currentStyle = .lightContent
                
                .onDisappear 
                     self.statusBarStyle.currentStyle = .default
                 
            
        
    

【讨论】:

这有明显的延迟,但确实有效。目前我已将 Info.plist 中的用户界面样式设置为 Light。 对于延迟问题,您可以创建一个 onWillDisappear ViewModifier。见***.com/a/65875968/13509092 请添加iOS14 SwiftUI应用生命周期代码示例。谢谢。

以上是关于SwiftUI:为特定视图设置状态栏颜色的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 设置状态栏背景颜色以与导航栏对齐

SwiftUI:状态栏颜色

更改状态栏颜色 SwiftUI 没有 UIHosting

无法为视图设置 iOS 状态栏颜色

为不同的视图控制器设置状态栏颜色

Safari 视图控制器使用错误的状态栏颜色