在iOS13中更改状态栏背景颜色

15

使用iOS 13后,我无法再通过"value for key"更改状态栏的背景颜色,因为无法再访问状态栏。 有人找到了解决办法吗?是否有任何关于iOS 13最终版本中可能实现这一点的信息?

我已经看到了不同的建议,例如使用UIApplications的StatusBarView(在Xcode 11 beta 7中不再可访问)或使用statusbarmanager。但是两者都无法访问状态栏。

let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
if statusBar.responds(to: #selector(setter: UIView.backgroundColor)) {
  statusBar.backgroundColor = <Some Color>
}

我希望状态栏能够得到我所需的背景颜色。


请检查此答案 https://dev59.com/WVMI5IYBdhLWcg3wS5nP#57152709。 - SAXENA
谢谢@SAXENA - 这似乎需要导航栏来设置外观。我正在寻找一种不需要导航栏的方法。 - Nij
@Nij请查看此链接以获取帮助:如何在iOS 13上更改状态栏的背景颜色和文本颜色? - Anbu.Karthik
13个回答

9

使用UIStatusBarManager的Objective-C版本:

UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame] ;
statusBar.backgroundColor = [UIColor whiteColor];
[[UIApplication sharedApplication].keyWindow addSubview:statusBar]

注意:如果您不使用SceneDelegate,请使用[UIApplication sharedApplication].statusBarFrame - Albert Renshaw

7

在您喜欢的ViewController上使用此功能

override func viewDidAppear(_ animated: Bool) {
    if #available(iOS 13, *)
    {
        let statusBar = UIView(frame: (UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame)!)
        statusBar.backgroundColor = UIColor.systemBackground
        UIApplication.shared.keyWindow?.addSubview(statusBar)
    }
}

您可以在“UIColor.systemBackground”中使用您的颜色。

1
我们需要将这个添加到每个ViewController吗?如果我们想在整个应用程序中执行呢? - Shubham Gupta
不工作,因为'keyWindow'在iOS 13.0中已被弃用:不应该用于支持多个场景的应用程序,因为它会返回所有连接场景中的关键窗口。 - Sky
2
当调用viewWillDisappear()时如何移除statusBar? - Anuranjan Bose
@ShubhamGupta 你找到整个应用程序执行的解决方案了吗? - TheTravloper

6

此代码适用于Swift 5+和iOS 13+

为了更改状态栏的背景颜色,我创建了一个UIViewController的基类,以便在所有的视图控制器中继承相同的代码。

将"statusBarColorChange()"添加到UIViewController扩展中。

extension UIViewController {

  func statusBarColorChange() {

    if #available(iOS 13.0, *) {

        let statusBar = UIView(frame: UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero)
        statusBar.backgroundColor = .appNavigationThemeColor
            statusBar.tag = 100
        UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.addSubview(statusBar)

    } else {

            let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
            statusBar?.backgroundColor = .appNavigationThemeColor

        }
    } }

创建基类并在其他类中继承。

class BaseClass: UIViewController {

   override func viewWillAppear(_ animated: Bool) {
       self.statusBarColorChange()
   }    
}

class ChatListViewController: BaseClass {} 

希望能够帮到您 :)

2
如果您没有使用 NavigationController,您可以在 ViewController 中设置基本视图的背景颜色。
view.backgroundColor = .blue

1

状态栏将尝试与应用程序的颜色匹配

如果您有导航栏

self.navigationBar.barTintColor = UIColor.blue

or

UINavigationBar.appearance().barTintColor = UIColor.blue

如果没有导航栏。
view.backgroundColor = UIColor.blue

如果您的背景是一个Web视图。
webView.scrollView.backgroundColor = UIColor.blue

可能还有我漏掉的其他情况


1

试试这个

if #available(iOS 13.0, *) {
    let navBarAppearance = UINavigationBarAppearance()
    navBarAppearance.configureWithOpaqueBackground()
    navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
    navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
    navBarAppearance.backgroundColor = <insert your color here>
    navigationBar.standardAppearance = navBarAppearance
    navigationBar.scrollEdgeAppearance = navBarAppearance
}

没有帮助,它只修复了NavigationBar颜色,而没有修复状态栏颜色。 - Vinodh

0

遵循@JaspreetKour的答案发现了一个问题,在通过推/弹出视图控制器多次导航到相同的视图控制器时,状态栏视图会一遍又一遍地添加,使状态栏颜色变暗。所以我添加了两行代码来解决这个问题,如果有人遇到相同的问题,可以查看这个答案,在将状态栏视图再次添加到窗口之前首先删除它。

然后在viewDidLoad中调用它,而不是viewWillAppear

func statusBarColorChange() {
    
    if #available(iOS 13.0, *) {
        if let viewStatus =  UIApplication.shared.windows.filter {$0.isKeyWindow}.first{
            viewStatus.viewWithTag(100)?.removeFromSuperview()
        }
        
        let statusBar = UIView(frame: UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero)
        statusBar.backgroundColor = AppConstant.Colors.navColor
        statusBar.tag = 100
        UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.addSubview(statusBar)
        
    } else {
        let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
        statusBar?.backgroundColor = AppConstant.Colors.navColor
    }
}

class BaseClass: UIViewController {

   override func viewDidLoad() {
       super.viewDidLoad()
       self.statusBarColorChange()
   }    
}

class ChatListViewController: BaseClass {}

0

代码适用于Swift 5+和iOS 13+

    public extension UIViewController {

func setStatusBar(color: UIColor) {
    
    let keyWindow = UIApplication.shared.connectedScenes
        .filter({$0.activationState == .foregroundActive})
        .compactMap({$0 as? UIWindowScene})
        .first?.windows
        .filter({$0.isKeyWindow}).first
    
    if #available(iOS 13.0, *) {
        
        let statusBar = UIView(frame: keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero)
        statusBar.backgroundColor = color
        statusBar.tag = 100
        keyWindow?.addSubview(statusBar)
        
    } else {
        
        let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
        statusBar?.backgroundColor = color
        
    }}}

我使用這個 答案,但在這種情況下編譯器會生成警告

'windows' 在 iOS 15.0 中已被棄用:改為在相關的視窗場景上使用 UIWindowScene.windows

因此這段代碼運行良好。

在你的 ViewController 的viewDidLoad方法中,請按以下方式使用此方法:

setStatusBar(color: UIColor(red: 28/255, green: 83/255, blue: 167/255, alpha: 1)) // or whatever color you want to set

0
JaspreetKour的答案是可行的,但是对于其他视图控制器重置状态栏颜色可能会非常困难(特别是如果您需要在状态栏下方放置图像内容)。将颜色设置为.clear无效。
更简单的解决方案是清除导航栏:
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.backgroundColor = .clear
navigationController?.navigationBar.isTranslucent = true

然后在您的视图控制器中添加一个UIView(将背景颜色设置为所需的颜色),并将其约束设置为超级视图的顶部(而不是边距)。

使用此技术,您的颜色将显示在状态栏下方,您无需处理statusBarManager(其所有属性都是只读的)。


0

在你的基础视图控制器中调用此方法

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)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接