每当我覆盖UserInterfaceStyle时如何更改状态栏颜色

Posted

技术标签:

【中文标题】每当我覆盖UserInterfaceStyle时如何更改状态栏颜色【英文标题】:How to change Status bar colour whenever I overrideUserInterfaceStyle 【发布时间】:2021-12-29 10:23:34 【问题描述】:

设置:

斯威夫特 5.5, Xcode 13.2

这个话题遍布网络,这里是one of them。好吧,我的应用有三个选项:

开:无论系统设置如何,都使用暗模式 关闭:无论系统设置如何,都使用灯光模式 系统:使用系统默认值(浅色或深色)

我有一个简单的类可以切换三个:

import SwiftUI

class Utilities: ObservableObject 

    // The default is to use the system's default.
    @AppStorage("theme") var theme: String = ""
    
    var userInterfaceStyle: ColorScheme? = .dark

    func overrideDisplayMode() 
        var userInterfaceStyle: UIUserInterfaceStyle

        if theme == "On" 
            userInterfaceStyle = .dark
         else if theme == "Off" 
            userInterfaceStyle = .light
         else 
            // System
            userInterfaceStyle = .unspecified
        
        
        let scenes = UIApplication.shared.connectedScenes
        let windowScene = scenes.first as? UIWindowScene
        let window = windowScene?.windows.first
        
        window?.overrideUserInterfaceStyle = userInterfaceStyle
        
    


它是如何更新的(减去按钮功能等):


@main
struct MainApp: App 
   @StateObject var utilities = Utilities()

  var body: some Scene 
    WindowGroup 
       ContentView()
       .onChange(of: utilities.theme, perform:  _ in
         utilities.overrideDisplayMode()
       )
       
       // Ensures the theme is set when app first loads
       .onAppear(perform: 
          utilities.overrideDisplayMode()
       
    
  


这很好用:主题化。唯一的问题是状态栏。每当我 overrideUserInterfaceStyletheme 更改时,我都想更改状态栏颜色。我怎样才能通过这种设置实现这一点?

【问题讨论】:

【参考方案1】:

这很简单。在 Apple 的 UIApplication.h 里面我看到了

public enum UIStatusBarStyle : Int 

    
    case `default` = 0 // Automatically chooses light or dark content based on the user interface style

    @available(ios 7.0, *)
    case lightContent = 1 // Light content, for use on dark backgrounds

    @available(iOS 13.0, *)
    case darkContent = 3 // Dark content, for use on light backgrounds

对我来说,关键部分是:

case default = 0 // 根据用户界面风格自动选择浅色或深色内容

所以继续:


[..]
func overrideDisplayMode() 
   [..]
        
    window?.overrideUserInterfaceStyle = userInterfaceStyle
    UIApplication.shared.statusBarStyle = .default // <-- THIS
        
 

“这个”不起作用,所以我做了一个完整的改变:

[..]

func overrideDisplayMode() 
    var userInterfaceStyle: UIUserInterfaceStyle
    // New
    var barStyle: UIStatusBarStyle

    if theme == "On" 
        userInterfaceStyle = .dark
        // New
        barStyle = .lightContent
     else if theme == "Off" 
        userInterfaceStyle = .light
        // New
        barStyle = .darkContent
     else 
        userInterfaceStyle = .unspecified
        // New
        barStyle = .default
    
    
    let scenes = UIApplication.shared.connectedScenes
    let windowScene = scenes.first as? UIWindowScene
    let window = windowScene?.windows.first
    
    window?.overrideUserInterfaceStyle = userInterfaceStyle
    // New
    UIApplication.shared.statusBarStyle = barStyle
    

然后在info.plist

查看基于控制器的状态栏外观:否

虽然此更改有效,但我收到了 iOS 13 的弃用警告:

'statusBarStyle' 在 iOS 13.0 中已弃用:改用窗口场景的 statusBarManager 属性。

我不知道如何使用 statusBarManager,但现在,我稍后会弄清楚那部分。

【讨论】:

以上是关于每当我覆盖UserInterfaceStyle时如何更改状态栏颜色的主要内容,如果未能解决你的问题,请参考以下文章

交互PopGesture时如何处理UITabBarController的子视图(如Flipboard)

避免直接改变道具,因为每当父组件重新渲染时,该值都会被覆盖

执行 Flux.map() 时如何处理错误

滚动时如何为 recyclerview 项目设置动画?

使用 QNetworkAccessManager 时如何处理代理

使用 seaborn 绘图时如何处理缺失值?