ios 如何在 Swift 3 中设置状态栏样式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38740648/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:50:09  来源:igfitidea点击:

How to set Status Bar Style in Swift 3

iosswiftuiviewcontrolleruistatusbarios-statusbar

提问by Willjay

I'm using Xcode 8.0 beta 4.

我正在使用 Xcode 8.0 beta 4。

In previous version, UIViewController have method to set the status bar style

在之前的版本中,UIViewController 有设置状态栏样式的方法

public func preferredStatusBarStyle() -> UIStatusBarStyle

However, I found it changed to a "Get ONLY varaiable" in Swift 3.

但是,我发现它在 Swift 3 中变成了“Get ONLY varaiable”。

public var preferredStatusBarStyle: UIStatusBarStyle { get } 

How can provide the style to use in my UIViewController?

如何提供在我的 UIViewController 中使用的样式?

回答by PRAVEEN

[UPDATED] For Xcode 10+ & Swift 4.2+

[更新] 适用于 Xcode 10+ 和 Swift 4.2+

This is the preferred method for iOS 7 and higher

这是 iOS 7 及更高版本的首选方法

In your application's Info.plist, set View controller-based status bar appearanceto YES.

在您的应用程序中Info.plist,设置View controller-based status bar appearanceYES.

Override preferredStatusBarStyle(Apple docs) in each of your view controllers. For example:

在每个视图控制器中覆盖preferredStatusBarStyleApple 文档)。例如:

override var preferredStatusBarStyle: UIStatusBarStyle {     
      return .lightContent
}

If you have preferredStatusBarStylereturning a different preferred status bar style based on something that changes inside of your view controller (for example, whether the scroll position or whether a displayed image is dark), then you will want to call setNeedsStatusBarAppearanceUpdate()when that state changes.

如果您preferredStatusBarStyle根据视图控制器内部的变化(例如,滚动位置或显示的图像是否暗)返回了不同的首选状态栏样式,那么您将需要setNeedsStatusBarAppearanceUpdate()在该状态更改时调用。

iOS before version 7, deprecated method

iOS 7 之前的版本,已弃用的方法

Apple has deprecated this, so it will be removed in the future. Use the above method so that you don't have to rewrite it when the next iOS version is released.

Apple 已弃用此,因此将来会删除它。使用上面的方法,这样下一个iOS版本发布的时候就不用重写了。

If your application will support In your application's Info.plist, set View controller-based status bar appearanceto NO.

如果您的应用程序将支持 在您的应用程序的 中Info.plist,设置View controller-based status bar appearanceNO

In appDelegate.swift, the didFinishLaunchingWithOptionsfunction, add:

appDelegate.swift,didFinishLaunchingWithOptions函数中,添加:

UIApplication.shared.statusBarStyle = .lightContent

For Navigation Controller

对于导航控制器

If you use a navigation controller and you want the preferred status bar style of each view controller to be used and set View controller-based status bar appearanceto YESin your application's info.plist

如果您使用导航控制器,并且希望使用每个视图控制器的首选状态栏样式并将其设置View controller-based status bar appearanceYES应用程序的info.plist

extension UINavigationController {
   open override var preferredStatusBarStyle: UIStatusBarStyle {
      return topViewController?.preferredStatusBarStyle ?? .default
   }
}

回答by Hexfire

Latest Update (Xcode 10+ / Swift 4.2+)

最新更新(Xcode 10+ / Swift 4.2+)

This article is left intact for anyone willing to understand the logic behind different approaches that were present for the past several years. Meanwhile, as of Xcode 10, Swift 4.2first approachis deprecatedand is no longer supported (i.e. will nottake effect if you try to employ it). It's still referred for your information to better understand the reasoning behind Plist.infoflag and customizing practice.

对于任何愿意了解过去几年出现的不同方法背后的逻辑的人,这篇文章都完好无损。同时,从Xcode 10 开始,Swift 4.2第一种方法已被弃用且不再受支持(即,如果您尝试使用它,则不会生效)。它仍然供您参考,以更好地理解Plist.info标志和自定义实践背后的推理。

Important clarification

重要说明

It is very important to understand two approaches to customizing the status bar appearance. They are different and should not be mixed.

了解自定义状态栏外观的两种方法非常重要。它们是不同的,不应混合使用。

First approach – one color for whole app (DEPRECATED since iOS7)

第一种方法 - 整个应用程序的一种颜色(自 iOS7 起已弃用)

In info.plist you find or create a key called

在 info.plist 中,您可以找到或创建一个名为

View controller-based status bar appearance

View controller-based status bar appearance

and set it to NO.

并将其设置为NO

What it does? It essentially establishes a setting that says that in your application, status bar appearance is not defined individually by each view controller. This is super important to understand. This means that you have uniform setting for entire app, for allscreens. There are two settings: default, which is black text on white background, or lightContent, which is white text on black background.

它能做什么?它基本上建立了一个设置,表明在您的应用程序中,状态栏外观不是由每个视图控制器单独定义的。理解这一点非常重要。这意味着您对所有屏幕的整个应用程序都有统一的设置。有两种设置:default,白底黑字,或lightContent,黑底白字。

To set one of these up (one setting for all screens):

要设置其中之一(所有屏幕的一项设置):

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    application.statusBarStyle = .lightContent // .default
    return true
}

This way you won't need to reestablish this setting on each view controller. However, you can always resort to this method to voluntarily change appearance.

这样你就不需要在每个视图控制器上重新建立这个设置。但是,您始终可以使用此方法来自愿更改外观。

Second approach – individual color for each view controller

第二种方法 - 每个视图控制器的单独颜色

This is the opposite. To make it work, go ahead to info.plist and set

这是相反的。要使其工作,请继续 info.plist 并设置

View controller-based status bar appearance

View controller-based status bar appearance

to YES

YES

This way, whenever a new view controller is open, status bar style is set individually if you insert this implementation in each UIViewControllerinstance you need:

这样,每当打开一个新的视图控制器时,如果您在每个UIViewController需要的实例中插入此实现,就会单独设置状态栏样式:

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

You have the same as in first, set either dark or light style for statusbar, individual to each view controller.

您与第一个相同,为状态栏设置深色或浅色样式,每个视图控制器都是单独的。

This property is fetched by UIKit in two scenarios:

UIKit 在两种情况下获取此属性:

  1. Upon initialization of the screen, when UI is being prepared.
  2. Upon calling setNeedsStatusBarAppearanceUpdate()in the code.
  1. 在屏幕初始化时,在准备 UI 时。
  2. 在调用setNeedsStatusBarAppearanceUpdate()代码时。

In latter case, you are eligible to manipulate the statusbar appearance by the following code:

在后一种情况下,您可以通过以下代码操作状态栏外观:

var isDark = false {
    didSet {
        setNeedsStatusBarAppearanceUpdate()
    }
}

override var preferredStatusBarStyle: UIStatusBarStyle {
    return isDark ? .lightContent : .default
}

func toggleAppearance() {
   isDark.toggle()
}

Then, whenever you call toggleAppearance(), statusbar style change will be triggered.

然后,无论何时调用toggleAppearance(),都会触发状态栏样式更改。

Third approach – Hack!

第三种方法——黑客!

There's a hack which allows to access statusbar directly:

有一个 hack 可以直接访问状态栏:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView {
        statusBar.backgroundColor = UIColor.blue
    }

    return true
}

Why hack? If you need status bar color other than black or white, you use undocumented API. You get statusBarobject using KVC and set its background color. Object you get this way is UIStatusBar, which is derived from UIViewand thus naturally supports backgroundColorproperty. This is dirty, not legal way, but so far it's the only way to set up custom color for statusbar (not taking into account UINavigationBarapproach, which allows to customize navbar+statusbar appearance altogether). It may well lead your app to being rejected. But maybe you're lucky. And if you are, in certain complex circumstances (like hierarchy of nested, child navigation and view controllers) this may be pretty much the only, or at least the less troublesome way to customize statusbar appearance (for example, to make it transparent)

为什么要破解?如果您需要黑色或白色以外的状态栏颜色,请使用未记录的 API。您statusBar使用 KVC获取对象并设置其背景颜色。你通过这种方式得到的对象是UIStatusBar,它是从属性派生的UIView,因此自然支持backgroundColor属性。这是肮脏的,不合法的方式,但到目前为止,它是为状态栏设置自定义颜色的唯一方法(不考虑UINavigationBar允许自定义导航栏+状态栏外观的方法)。这很可能会导致您的应用被拒绝。但也许你很幸运。如果你是,在某些复杂的情况下(比如嵌套的层次结构、子导航和视图控制器),这可能是唯一的,或者至少是自定义状态栏外观(例如,使其透明)不太麻烦的方法

Xcode 10+, Swift 4.2

Xcode 10+,Swift 4.2

There are no alternatives any more: developer should let eachview controller define statusbar appearance, by setting the flag to YES(or omitting this action, because it's YES by default) and following above instructions.

没有其他选择了:开发人员应该让每个视图控制器定义状态栏外观,通过将标志设置为YES(或省略此操作,因为默认情况下它是 YES)并遵循上述说明。



Bonus

奖金

Hack-based solution you might (although not encouraged to) use in complex circumstances in order to voluntarily change statusbar appearance at any stage. Color-wise, the following extension method does exactly what you could have done with regular approach. You can adjust it to your needs.

您可能(尽管不鼓励)在复杂情况下使用基于 Hack 的解决方案,以便在任何阶段自愿更改状态栏外观。在颜色方面,以下扩展方法完全可以完成您可以使用常规方法完成的操作。您可以根据自己的需要进行调整。

extension UIViewController {
    func setStatusBarStyle(_ style: UIStatusBarStyle) {
        if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView {
            statusBar.backgroundColor = style == .lightContent ? UIColor.black : .white
            statusBar.setValue(style == .lightContent ? UIColor.white : .black, forKey: "foregroundColor")
        }
    }
}

回答by Abizern

You could try to override the value returned, rather than setting it. The method is declared as { get }, so just provide a getter:

您可以尝试覆盖返回的值,而不是设置它。该方法声明为 { get },因此只需提供一个 getter:

 override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

If you set this conditionally, you'll need to call setNeedsStatusBarAppearanceUpdate()so it'll animate the change when you're ready

如果您有条件地设置它,则需要调用setNeedsStatusBarAppearanceUpdate()它以便在您准备好时为更改设置动画

回答by Gracu

Swift 3 & 4, iOS 10 & 11, Xcode 9 & 10
For me, this method doesn't work:

Swift 3 & 4、iOS 10 & 11、Xcode 9 & 10
对我来说,这个方法不起作用:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

when I used to each view controller, but this worked:

当我习惯于每个视图控制器时,但这有效:

  • In file info.list, add row: View controller-based status bar appearanceand set to NO

  • Next in appdelegate:

    UIApplication.shared.statusBarStyle = .lightContent
    
  • 在文件 info.list 中,添加 row:View controller-based status bar appearance并设置为NO

  • 接下来在 appdelegate 中:

    UIApplication.shared.statusBarStyle = .lightContent
    

回答by Mr. Xcoder

If you want to change the statusBar's color to white, for all of the views contained in a UINavigationController, add this inside AppDelegate:

如果要将statusBar的颜色更改为白色,对于包含在 a 中的所有视图,请在其中UINavigationController添加AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    UINavigationBar.appearance().barStyle = .blackOpaque
    return true
}

This code:

这段代码:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

does notwork for UIViewControllerscontained in a UINavigationController, because the compiler looks for the statusBarStyleof the UINavigationController, not for the statusBarStyleof the ViewControllerscontained by it.

为工作UIViewControllers包含在UINavigationController为,因为编译器的外观statusBarStyleUINavigationController,而不是为statusBarStyleViewControllers被它包含。

Hope this helps those who haven't succeeded with the accepted answer!

希望这可以帮助那些没有成功接受答案的人!

回答by alex de oliveira

If you want to change the status bar style any time after the view has appeared you can use this:

如果您想在视图出现后随时更改状态栏样式,您可以使用:

  • In file info.list add row: View controller-based status bar appearanceand set it to YES

    var viewIsDark = Bool()
    
    func makeViewDark() {
    
        viewIsDark = true
        setNeedsStatusBarAppearanceUpdate()
    }
    
    func makeViewLight() {
    
        viewIsDark = false
        setNeedsStatusBarAppearanceUpdate()
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
    
        if viewIsDark {
            return .lightContent 
        } else {
            return .default 
        } 
    }
    
  • 在文件 info.list 中添加行:查看基于控制器的状态栏外观并将其设置为YES

    var viewIsDark = Bool()
    
    func makeViewDark() {
    
        viewIsDark = true
        setNeedsStatusBarAppearanceUpdate()
    }
    
    func makeViewLight() {
    
        viewIsDark = false
        setNeedsStatusBarAppearanceUpdate()
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
    
        if viewIsDark {
            return .lightContent 
        } else {
            return .default 
        } 
    }
    

回答by Himanshu padia

You need to add below key in your Info.plist file:

您需要在 Info.plist 文件中添加以下键:

View controller-based status bar appearancewith boolean value set to NO

View controller-based status bar appearance布尔值设置为 NO

In your appdelegate class, in didFinishLaunchingWithOptionsmethod before return.

在您的 appdelegate 类中,在didFinishLaunchingWithOptions返回之前的方法中。

let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
    statusBar.backgroundColor = UIColor.red
}
UIApplication.shared.statusBarStyle = .lightContent

change backgroundColorand statusBarStyleas per requirement.

更改backgroundColorstatusBarStyle根据要求。

回答by Vivek

Xcode 10 or later

Xcode 10 或更高版本

Tested in Swift 5

在 Swift 5 中测试

No code required just follow below steps.

无需代码,只需按照以下步骤操作即可。

If you want to change the status bar in the whole app.

如果您想更改整个应用程序中的状态栏。

  1. Select Project from Project Navigator (left side panel).
  2. Select target.
  3. Select General tab.
  4. Find Deployment info.
  5. Change status bar style to Light(for dark background "Light", Light background "Default")
  1. 从项目导航器(左侧面板)中选择项目。
  2. 选择目标。
  3. 选择常规选项卡。
  4. 查找部署信息。
  5. 将状态栏样式更改为Light(对于深色背景“Light”,浅色背景“Default”

Don't forget info.plist changes

不要忘记 info.plist 更改

  1. Select Info tab
  2. Add this key into your plist file "View controller-based status bar appearance" = NO
  1. 选择信息选项卡
  2. 将此键添加到您的 plist 文件“查看基于控制器的状态栏外观”= NO

Run your project and check it.

运行你的项目并检查它。

My project in swift 5 and Xcode 10.2 & 11.0

我在 swift 5 和 Xcode 10.2 & 11.0 中的项目

回答by Bryan Norden

You can also do this in storyboard

您也可以在故事板中执行此操作

  1. Create a new entry in info.plist "View controller-based status bar appearance" set it to "YES".
  2. Go to your storyboard and then select the navigation controller that you want to change. Click on the navigation bar from Storyboard document outline section (left panel on storyboard)
  3. Go to the right panel and click the attributes section
  4. Under the Navigation Bar section you will see style. Select the style you would like (default is for black and black is for white)
  1. 在 info.plist 中创建一个新条目“查看基于控制器的状态栏外观”将其设置为“是”。
  2. 转到故事板,然后选择要更改的导航控制器。单击 Storyboard 文档大纲部分的导航栏(情节提要的左侧面板)
  3. 转到右侧面板并单击属性部分
  4. 在导航栏部分下,您将看到样式。选择您喜欢的样式(默认为黑色,黑色为白色)

You will have to do this for each navigation controller you have. However, any views under that navigation controller will change all the view's status bars style/color to the one you just selected. I find this option better because you can see your results instantly and do not have to add extra lines of code in every view controller.

您必须为您拥有的每个导航控制器执行此操作。但是,该导航控制器下的任何视图都会将视图的所有状态栏样式/颜色更改为您刚刚选择的样式/颜色。我觉得这个选项更好,因为你可以立即看到你的结果,而不必在每个视图控制器中添加额外的代码行。

enter image description here

在此处输入图片说明

(Done with Xcode 8.3.3 in an all Swift project)

(在全 Swift 项目中使用 Xcode 8.3.3 完成)

回答by Doci

For people looking to change status bar for all viewcontrollers on: iOS 11, Swfit 4/5 solution is pretty easy.

对于希望更改所有视图控制器状态栏的人:iOS 11,Swfit 4/5 解决方案非常简单。

1)Info.plist add:

1)Info.plist 添加:

View controller-based status bar appearance -> NO

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

2)Left side of XCode slect project > Targets> Select your project > Under General > Deployment Info > Select Status Bar Style: Light

2)XCode slect 项目的左侧 >目标> 选择你的项目 > 在 General > Deployment Info > Select Status Bar Style: Light

If you want to change status bar only for one viewcontroller, on viewDidLoad add:

如果您只想更改一个 viewcontroller 的状态栏,请在 viewDidLoad 上添加:

2.1) Info.plist

2.1) Info.plist

View controller-based status bar appearance -> YES

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

2.2)

2.2)

override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}

Objective-C (or react native) changing from App Delegate:

从 App Delegate 更改的 Objective-C(或 react native):

1)Info.plist add:

1)Info.plist 添加:

View controller-based status bar appearance -> NO

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

2)AppDelegate -> didFinishLaunchingWithOptions

2)AppDelegate -> didFinishLaunchingWithOptions

[[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDarkContent animated:YES];

Changing status bar do not worktrying to do push(navigation controllers), only on presenting modally viewcontrollers.

更改状态栏在尝试执行推送(导航控制器)时不起作用,仅适用于呈现模态视图控制器。