【问题标题】:Change Status Bar Background Color in Swift 3在 Swift 3 中更改状态栏背景颜色
【发布时间】:2017-02-09 16:12:30
【问题描述】:

在 XCode 7.3.x 中,我更改了 StatusBar 的背景颜色:

func setStatusBarBackgroundColor(color: UIColor) {
guard  let statusBar = UIApplication.sharedApplication().valueForKey("statusBarWindow")?.valueForKey("statusBar") as? UIView else {
    return
}
statusBar.backgroundColor = color
}

但这似乎不再适用于 Swift 3.0。

我试过了:

func setStatusBarBackgroundColor(color: UIColor) {
guard  let statusBar = (UIApplication.shared.value(forKey: "statusBarWindow") as AnyObject).value(forKey: "statusBar") as? UIView else {
    return
}
statusBar.backgroundColor = color
}

但它给了我:

this class is not key value coding-compliant for the key statusBar.

任何想法如何用 XCode8/Swift 3.0 改变它?

【问题讨论】:

    标签: ios swift swift3 statusbar uistatusbar


    【解决方案1】:
    extension UIApplication {
        var statusBarView: UIView? {
            if responds(to: Selector(("statusBar"))) {
                return value(forKey: "statusBar") as? UIView
            }
            return nil
        }
    }
    
    UIApplication.shared.statusBarView?.backgroundColor = .red
    

    iOS 13 更新

    在 UIApplication 上调用 -statusBar 或 -statusBarWindow 的应用程序:此代码 必须更改,因为不再有状态栏或状态栏 窗户。改为在窗口场景中使用 statusBarManager 对象。

    参考How to change the status bar background color and text color on iOS 13?

    【讨论】:

    • 这根本不是一个好习惯,我强烈建议不要使用这种方法,因为这个UIView 是私有的。我很想知道您的应用是否获得批准。
    • @iGranDav 为什么这不是一个好习惯。 value(forKey key: String) 方法是开放的,所以我假设它可以使用。你能解释一下吗。如果这是不好的做法,您将如何更改背景颜色或状态栏。这种方法对我有用。我尝试向AppDelegate 中的window 对象添加子视图,但没有成功。
    • @breaktop 使用 value(forKey key: String) 方法,您正在使用 objc 运行时的 KVC 仅在运行时访问您不应该访问的视图(顺便说一句,没有文档引用它)。此构造在 iOS 10 下使用,但在 iOS 9 下不使用(您需要首先访问statusBarWindow),并且您绝对不知道它会在 iOS 11 下持续存在。内部构造并且没有文档意味着 Apple 在这里没有任何要遵守的合同。
    • @SanketBhavsar 我还没有因为使用它而被拒绝
    • 我在 iPhone X 上使用这种方法有问题。激活应用切换器(主页指示器)手势后,背景颜色变为透明。
    【解决方案2】:

    “更改”状态栏背景颜色:

    let statusBarView = UIView(frame: UIApplication.shared.statusBarFrame)
    let statusBarColor = UIColor(red: 32/255, green: 149/255, blue: 215/255, alpha: 1.0)
    statusBarView.backgroundColor = statusBarColor
    view.addSubview(statusBarView)
    

    更改状态栏文字颜色:

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
    

    更新:请注意,当视图旋转时,状态栏框架会发生变化。您可以通过以下方式更新创建的子视图框架:

    • 使用自动调整大小掩码: statusBarView.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
    • 观察NSNotification.Name.UIApplicationWillChangeStatusBarOrientation
    • 或覆盖viewWillLayoutSubviews()

    【讨论】:

    • UIApplication.shared.statusBarUIView?.backgroundColor = .white
    • @JainilPatel 无效
    【解决方案3】:

    通过使用 Swift 3 和 4,您可以使用下面的代码 sn-p。它使用valueForKeyPathUIApplication找到视图,并将其设置为背景色。

    guard let statusBarView = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView else {
            return
        }
    statusBarView.backgroundColor = UIColor.red
    

    Objective-C

    UIView *statusBarView = [UIApplication.sharedApplication valueForKeyPath:@"statusBarWindow.statusBar"];
    if (statusBarView != nil)
    {
        statusBarView.backgroundColor = [UIColor redColor];
    }
    

    【讨论】:

      【解决方案4】:

      对于 Xcode 9 和 iOS 11: 我们将尝试实现的状态栏样式是带有白色内容的状态栏。转到 ViewController.swift 文件并添加以下代码行。

      override var preferredStatusBarStyle: UIStatusBarStyle {
      
           return .lightContent
      
      }
      

      或者从项目设置选项中,您可以更改状态栏的样式:

      接下来,返回 Storyboard,选择 View Controller,然后在 Editor 菜单中选择 Embed in Navigation Controller。选择导航栏并在属性检查器中将栏色调设置为红色。故事板将如下所示。

      构建并运行项目,状态栏的内容又变暗了,这是默认的。原因是,iOS 要求导航控制器的状态栏样式,而不是包含的视图控制器。

      要更改应用内所有导航控制器的样式,请在 AppDelegate.swift 文件中更改以下方法。

        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
          // Override point for customization after application launch.
      
          UINavigationBar.appearance().barStyle = .blackOpaque
          return true
          }
      

      再次构建并运行项目,这次状态栏的内容变成了白色。

      【讨论】:

      【解决方案5】:

      我有一个自定义解决方案,用于在 iOS 13 及更低版本上更改状态栏。以下是如何做到这一点:

      if #available(iOS 13.0, *) {
         let app = UIApplication.shared
         let statusBarHeight: CGFloat = app.statusBarFrame.size.height
      
         let statusbarView = UIView()
         statusbarView.backgroundColor = UIColor.red
         view.addSubview(statusbarView)
      
         statusbarView.translatesAutoresizingMaskIntoConstraints = false
         statusbarView.heightAnchor
           .constraint(equalToConstant: statusBarHeight).isActive = true
         statusbarView.widthAnchor
           .constraint(equalTo: view.widthAnchor, multiplier: 1.0).isActive = true
         statusbarView.topAnchor
           .constraint(equalTo: view.topAnchor).isActive = true
         statusbarView.centerXAnchor
           .constraint(equalTo: view.centerXAnchor).isActive = true
      
      } else {
            let statusBar = UIApplication.shared.value(forKeyPath: 
         "statusBarWindow.statusBar") as? UIView
            statusBar?.backgroundColor = UIColor.red
      }
      

      Gist

      另外,查看文章iOS 13 How to Change StatusBar Color?

      最后一件事,你仍然可以改变状态栏样式:

       override var preferredStatusBarStyle : UIStatusBarStyle {
          return UIStatusBarStyle.lightContent
          //return UIStatusBarStyle.default   // Make dark again
      }
      

      【讨论】:

      • 被低估的解决方案。竖起大拇指
      【解决方案6】:

      对于 iOS 11 和 Xcode 9,请使用以下步骤。

      1. 创建 UIApplication 类的扩展:

        extension UIApplication { var statusBarView: UIView? { return value(forKey: "statusBar") as? UIView } }

      2. 在你的班级或任何你想改变状态栏背景颜色的地方:

        UIApplication.shared.statusBarView?.backgroundColor = .red

      3. 对于状态栏的浅色内容或深色内容,只需转到 Info.plist 并添加以下值为 NO 的值行。

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

      1. 现在只需在项目设置的常规选项卡中设置灯光内容或您需要的任何内容。

      【讨论】:

        【解决方案7】:
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any] ?) -> Bool {
            // Override point for customization after application launch.
        
            UINavigationBar.appearance().barStyle = .blackOpaque
            return true
        }
        

        这对我有用,因为我的导航栏TintColor 是黑色的并且看不到状态栏。

        当设置上面的代码时,它 didFinishLaunch 状态栏显示为白色。

        【讨论】:

          【解决方案8】:

          我做了这个扩展来改变状态栏的颜色。它不依赖于密钥。 所以使用起来更安全

          public extension UIViewController {
              func setStatusBar(color: UIColor) {
                  let tag = 12321
                  if let taggedView = self.view.viewWithTag(tag){
                      taggedView.removeFromSuperview()
                  }
                  let overView = UIView()
                  overView.frame = UIApplication.shared.statusBarFrame
                  overView.backgroundColor = color
                  overView.tag = tag
                  self.view.addSubview(overView)
              }
          }
          

          这是视图控制器中任何地方的用法:

          setStatusBar(color: .red)

          【讨论】:

          • 它无法在 iPhone X 设备上正常工作。它只覆盖了一半的状态栏。
          【解决方案9】:

          试试这个

          转到您的应用 info.plist

          1. 将基于视图控制器的状态栏外观设置为 NO
          2. 将状态栏样式设置为 UIStatusBarStyleLightContent

          然后转到您的应用委托并将以下代码粘贴到您设置 Windows 的 RootViewController 的位置。

          #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
          
          if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
          {
              UIView *view=[[UIView alloc] initWithFrame:CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.width, 20)];
              view.backgroundColor=[UIColor blackColor];
              [self.window.rootViewController.view addSubview:view];
          }
          

          【讨论】:

          • 状态栏,不是导航栏。
          【解决方案10】:

          在第一个视图控制器中写入:

          UIApplication.shared.statusBarUIView?.backgroundColor = .white
          
          
          
          
          
          
          extension UIApplication {
              var statusBarUIView: UIView? {
                  if #available(iOS 13.0, *) {
                      let tag = 38482458385
                      if let statusBar = self.keyWindow?.viewWithTag(tag) {
                          return statusBar
                      } else {
                          let statusBarView = UIView(frame: UIApplication.shared.statusBarFrame)
                          statusBarView.tag = tag
          
                          self.keyWindow?.addSubview(statusBarView)
                          return statusBarView
                      }
                  } else {
                      if responds(to: Selector(("statusBar"))) {
                          return value(forKey: "statusBar") as? UIView
                      }
                  }
                  return nil
              }
          }
          

          【讨论】:

          • 'keyWindow' 在 iOS 13.0 中已弃用:不应用于支持多个场景的应用程序,因为它会在所有连接的场景中返回一个关键窗口
          • 当我写答案时,我正在学习转变语言。所以这个答案太老了。
          • 不用担心。只是让未来的互联网居民知道 iOS 已经改变了它的工作方式。目前我正在使用这个解决方案:gist.github.com/eonist/ffc0788c57d620aac43ae15cec4b00a9
          【解决方案11】:

          以前的代码:-

          func setStatusBarBackgroundColor(color: UIColor) {
                  guard let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView else { return }
          
                  statusBar.backgroundColor = color
              }
          

          我的应用程序出现崩溃显示原因:'在 UIApplication 上调用 -statusBar 或 -statusBarWindow 的应用程序:必须更改此代码,因为不再有状态栏或状态栏窗口。在窗口场景中使用 statusBarManager 对象。'

          更新代码-

            if #available(iOS 13.0, *) {
                      let statusBar = UIView(frame: UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero)
                       statusBar.backgroundColor = UIColor.init(red: 237.0/255.0, green: 85.0/255.0, blue: 61.0/255.0, alpha: 1.0)
                       UIApplication.shared.keyWindow?.addSubview(statusBar)
                  } else {
                       UIApplication.shared.statusBarView?.backgroundColor = UIColor.init(red: 237.0/255.0, green: 85.0/255.0, blue: 61.0/255.0, alpha: 1.0)
                  }
          

          这段代码在 swift 5.2 中运行

          enter image description here

          【讨论】:

          • 什么是statusBarView?
          【解决方案12】:

          您可以在应用程序启动期间或视图控制器的 viewDidLoad 期间设置状态栏的背景颜色。

          extension UIApplication {
          
              var statusBarView: UIView? {
                  return value(forKey: "statusBar") as? UIView
              }
          
          }
          
          // Set upon application launch, if you've application based status bar
          class AppDelegate: UIResponder, UIApplicationDelegate {
          
              var window: UIWindow?
          
              func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
                  UIApplication.shared.statusBarView?.backgroundColor = UIColor.red
                  return true
              }
          }
          
          
          or 
          // Set it from your view controller if you've view controller based statusbar
          class ViewController: UIViewController {
          
              override func viewDidLoad() {
                  super.viewDidLoad()
          
                  UIApplication.shared.statusBarView?.backgroundColor = UIColor.red
              }
          
          }
          



          结果如下:

          【讨论】:

          • 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“在 UIApplication 上调用 -statusBar 或 -statusBarWindow 的应用程序:必须更改此代码,因为不再有状态栏或状态栏窗口。改为在窗口场景中使用 statusBarManager 对象。'
          • @Sentry.co - 我在 3 年前测试并发布了这个答案。欢迎您更新此答案并提高其质量,使其与 Swift/iOS 中的最新技术变化保持一致。
          • 是的。我的评论旨在警告那些试图解决这个问题的人也看看其他地方,因为它不再起作用了。我现在让它工作了,但它需要大量的研究,因为还没有人在 StackOverflow 上解决它。这是适用于 iOS 15 的解决方案。(一点也不优雅)gist.github.com/eonist/ffc0788c57d620aac43ae15cec4b00a9
          【解决方案13】:

          可能的解决方案是在 viewController 上添加将用作 statusBar 背景的视图:

          let frame = screenController.view.convert(UIApplication.shared.statusBarFrame, to: screenController.view)
          let backview = UIView(frame: frame)
          
          backview.backgroundColor = backgroundColor
          screenController.view.addSubview(backview)
          screenController.view.bringSubviewToFront(backview)
          

          【讨论】:

          • 这一次在 Swift 5 中崩溃
          【解决方案14】:

          在您的扩展文件中添加以下代码以在 swift 4 及更高版本中编辑您的状态栏:

          extension UIApplication {
              var statusBarView: UIView? {
                  if responds(to: Selector(("statusBar"))) {
                      return value(forKey: "statusBar") as? UIView
                  }
                  return nil
              }
          }
          

          现在,我们可以通过在 ViewController 类中添加以下行来编辑状态栏:

          UIApplication.shared.statusBarView?.backgroundColor = <Your Color name>
          
          ex: UIApplication.shared.statusBarView?.backgroundColor = .red
          

          希望,这会有所帮助。 谢谢

          【讨论】:

            【解决方案15】:

            IOS 15、Xcode 13.2.1、Swift 5

            我能够使用以下方法使其正常工作而不会出现错误或警告:

            func statusBarColor() {
                if #available(iOS 13.0, *) {
                    
                    let statusBar2 =  UIView()
                    if UIApplication.shared.currentScene?.statusBarManager!.statusBarFrame != nil {
                        statusBar2.frame = (UIApplication.shared.currentScene?.statusBarManager!.statusBarFrame)!
                        statusBar2.backgroundColor = UIColor.init(named: "BackGroundColor")
                        UIApplication.shared.windows.first?.addSubview(statusBar2)
                    }
                } else {
                    let statusBar2: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
                    statusBar2.backgroundColor = UIColor.init(named: "BackGroundColor")
                }
            }
            

            使用:在viewDidLoad中调用函数,用于单场景应用或只需要改变单个statusBar颜色的应用。对于有多个场景调用不同状态栏颜色的应用程序,我建议在 viewWillAppear 中调用该函数。

            【讨论】:

              猜你喜欢
              • 2015-10-09
              • 2015-09-26
              • 2019-11-20
              • 2016-10-16
              • 1970-01-01
              • 1970-01-01
              • 2019-11-05
              • 1970-01-01
              相关资源
              最近更新 更多