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

Sco*_*her 4 iphone ios swift swiftui

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

我已经尝试了此处列出的解决方案..“如何更改 iOS 中状态栏文本颜色”,但这为整个应用程序设置了它。

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

有任何想法吗?

Asp*_*eri 5

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

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

这是方法,scratchy,(假设目标 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法..

1)场景委托中的某处

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        ...
        window.rootViewController = MyHostingController(rootView: contentView)
Run Code Online (Sandbox Code Playgroud)

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
                 }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这会带来明显的延迟,但它确实有效。我目前已将 Info.plist 中的用户界面样式设置为 Light。 (3认同)
  • 请添加 iOS14 SwiftUI 应用程序生命周期代码示例。谢谢。 (2认同)