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

问题描述 投票:162回答:30

我正在使用Xcode 8.0 beta 4。

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

public func preferredStatusBarStyle() -> UIStatusBarStyle

但是,我发现它在Swift 3中改为“Get ONLY变量”。

public var preferredStatusBarStyle: UIStatusBarStyle { get } 

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

ios swift uiviewcontroller uistatusbar ios-statusbar
30个回答
443
投票

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

在应用程序的Info.plist中,将“查看基于控制器的状态栏外观”设置为YES。

Override preferredStatusBarStyle in each of your view controllers。例如:

override var preferredStatusBarStyle: UIStatusBarStyle {     
      return .lightContent
}

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

如果使用导航控制器并且希望使用每个视图控制器的首选状态栏样式,请参阅https://stackoverflow.com/a/41026726/1589422

iOS 7之前的版本,不推荐使用的方法

Apple has deprecated this,所以它将来会被删除。使用上面的方法,以便在下一个iOS版本发布时不必重写它。

如果您的应用程序将支持在您的应用程序的Info.plist中,请将“查看基于控制器的状态栏外观”设置为NO。

appDelegate.swiftdidFinishLaunchingWithOptions函数,添加:

UIApplication.shared.statusBarStyle = .lightContent

6
投票

斯威夫特3

在Info.plist中添加一行称为“基于视图控制器的状态栏外观”,并将其值设置为No

class YourViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        UIApplication.shared.statusBarStyle = .lightContent //or .default
        setNeedsStatusBarAppearanceUpdate()

    }

}

6
投票

处理导航栏时,状态栏文本颜色似乎有一个小问题。

如果您希望.plist条目将基于控制器的状态栏外观设置为YES,则当您有彩色导航栏时,它有时不起作用。

例如:

override func viewWillAppear(_ animated: Bool) {
    let nav = self.navigationController?.navigationBar
    nav?.barTintColor = .red
    nav?.tintColor = .white
    nav?.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    setNeedsStatusBarAppearanceUpdate()
}

override var preferredStatusBarStyle: UIStatusBarStyle {return .lightContent}

即使您在AppDelegate中设置了以下代码,上面的代码也不起作用:

UIApplication.shared.statusBarStyle = .lightContent

对于那些仍在苦苦挣扎的人来说,显然它会以某种方式判断导航栏中的状态栏是否需要亮或暗。所以,我设法通过在viewWillAppear中添加以下行来解决这个问题:

nav?.barStyle = UIBarStyle.black

当条形样式为黑色时,它会侦听被覆盖的变量。希望这有助于某人:)


5
投票

Xcode 8.3.1,Swift 3.1

  1. 在info.plist中创建一个新条目“查看基于控制器的状态栏外观”将其设置为“NO”。
  2. 打开AppDelegate.swift并在“didFinishLaunchingWithOptions”方法中添加以下行:

application.statusBarStyle = .lightContent


5
投票

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

1)Info.plist add:

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

2)XCode选择项目的左侧>目标>选择项目>常规>部署信息>选择状态栏样式:光

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

override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}

4
投票

Swift 4.0请在“didFinishLaunchingWithOptions launchOptions:”Appdelegate类中使用此代码

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

4
投票

这是关于状态栏样式变化的Apple Guidelines/Instruction

如果要设置状态栏样式,应用程序级别,然后在UIViewControllerBasedStatusBarAppearance文件中将NO设置为.plist。并在您的appdelegate> didFinishLaunchingWithOptions添加以下ine(以编程方式,您可以从app委托执行此操作)。

目标C.

[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

迅速

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

如果要设置状态栏样式,请在视图控制器级别执行以下步骤:

  1. 如果您只需要在UIViewController级别设置状态栏样式,请在UIViewControllerBasedStatusBarAppearance文件中将YES设置为.plist
  2. 在viewDidLoad中添加函数 - setNeedsStatusBarAppearanceUpdate
  3. 覆盖视图控制器中的preferredStatusBarStyle。

目标C.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setNeedsStatusBarAppearanceUpdate];
}

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

迅速

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

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

根据状态栏样式设置级别设置.plist的值。


4
投票

加入@Krunal https://stackoverflow.com/a/49552326/4697535的伟大asnwer

如果你使用UINavigationControllerpreferredStatusBarStyle将对UIViewController没有影响。

Xcode 10和Swift 4。

设置自定义UINavigationController

例:

class LightNavigationController: UINavigationController {

   open override var preferredStatusBarStyle: UIStatusBarStyle {
       return .lightContent
   }
}

使用应用级解决方案的扩展程序:

extension UINavigationController {

  open override var preferredStatusBarStyle: UIStatusBarStyle {
      guard let index = tabBarController?.selectedIndex else { return .default }
      switch index {
      case 0, 1, 2: return .lightContent // set lightContent for tabs 0-2
      default: return .default // set dark for tab 3
      }
  }
}

3
投票

这对我有用

View controller-based status bar外观设置为plist中的NO然后在UIViewController viewDidAppear中添加以下行

UIApplication.shared.setStatusBarStyle(UIStatusBarStyle.lightContent, animated: true)

3
投票

迅捷3

如果在Info.plist中查看基于控制器的状态栏外观= YES

然后对所有NavigationController使用此扩展

    extension UINavigationController
    {
        override open var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
         }
     }

如果没有UINavigationController,只有UIViewController,那么使用下面的代码:

    extension UIViewController
    {
        override open var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
         }
     }

3
投票
override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

这对我有用:)我的导航控制器嵌入在我的视图控制器中,隐藏了导航栏。我想在应用程序的某些视图上设置状态栏指示灯。


141
投票

Latest Update (Xcode 10+ / Swift 4.2+)

对于愿意理解过去几年中存在的不同方法背后的逻辑的人来说,本文保持不变。同时,从Xcode 10开始,不再支持Swift 4.2 first approach is deprecated(即如果你尝试使用它也不会生效)。它仍然提供给您的信息,以便更好地理解Plist.info旗帜和定制实践背后的原因。

Important clarification

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

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

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

View controller-based status bar appearance

并将其设置为NO。

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

要设置其中一个(所有屏幕都有一个设置):

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

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

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

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

View controller-based status bar appearance

是的

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

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

您与第一个相同,为状态栏设置暗或浅样式,为每个视图控制器设置个别。

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

  1. 在初始化屏幕时,正在准备UI。
  2. 在代码中调用setNeedsStatusBarAppearanceUpdate()

在后一种情况下,您有资格通过以下代码操纵状态栏外观:

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

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

func toggleAppearance() {
   isDark.toggle()
}

然后,每当您调用toggleAppearance()时,将触发状态栏样式更改。

第三种方法 - 哈克!

有一个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
}

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

Xcode 10 +,Swift 4.2

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


奖金

您可能(虽然不鼓励)在复杂环境中使用基于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")
        }
    }
}

3
投票

Xcode 10 or later

No code required just follow below steps.

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

  1. 从Project Navigator(左侧面板)中选择Project。
  2. 选择目标。
  3. 选择常规选项卡。
  4. 查找部署信息。
  5. 将状态栏样式更改为Light(对于深色背景“Light”,浅色背景“Default”)

不要忘记info.plist的变化

  1. 选择信息选项卡
  2. 将此键添加到plist文件“查看基于控制器的状态栏外观”= NO

运行您的项目并检查它。

我在swift 5和Xcode 10.2中的项目


2
投票

Swift 4+

对于白色状态栏文本:

navigationController.navigationBar.barStyle = .blackTranslucent

2
投票

iOS 11.2

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

    UINavigationBar.appearance().barStyle = .black

    return true
}

2
投票

您可以使用名为“shouldStatusBarDark”的bool属性来切换状态栏颜色。您还可以更新其值以在滚动时更改状态栏颜色。

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

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

 func scrollViewDidScroll(_ scrollView: UIScrollView) {
     let offSetY = scrollView.contentOffset.y
     if offSetY > 50 {
         UIView.animate(withDuration: 0.4, animations: {
             self.navView.alpha = 1
             self.shouldStatusBarDark = true
         })
     } else {
         UIView.animate(withDuration: 0.4, animations: {
             self.navView.alpha = 0
             self.shouldStatusBarDark = false
         })
     }
 }

2
投票

这些答案中的大多数都是重新散列的,但在使用深色背景时,它们都没有真正解决我的启动画面问题。

我在info.plist中使用以下内容来解决这个问题,这会产生一个轻巧的状态栏。

<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>

1
投票

如果您收到警告:在iOS 9.0中不推荐使用'statusBarStyle'的Setter:使用 - [UIViewController preferredStatusBarStyle],然后将状态栏设置为亮或暗使用以下代码:

//To set the status bar to white
self.navigationController?.navigationBar.barStyle = .black //or .blackTranslucent

//To set the status bar to black
self.navigationController?.navigationBar.barStyle = .default

这不会使您的navBar更改它纯粹指示样式,因此相应地更改状态栏。

NB。您需要确保在info.plist中设置。

View controller-based status bar appearance to YES

0
投票

我得到了:

覆盖var必须与其封闭类型一样可访问

通过添加public来解决这个问题:

override public var preferredStatusBarStyle: UIStatusBarStyle {
    get {
        return .lightContent
    }
}

在Swift3 iOS10上。


0
投票

对于目标C,只需在应用程序的didFinishLaunch方法中添加此行

UIApplication.sharedApplication.statusBarStyle = UIStatusBarStyleLightContent;

0
投票

使用WebkitView

Swift 9.3 iOS 11.3

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

    @IBOutlet weak var webView: WKWebView!
    var hideStatusBar = true

    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setNeedsStatusBarAppearanceUpdate()
        let myURL = URL(string: "https://www.apple.com/")
        let myRequest = URLRequest(url: myURL!)
        UIApplication.shared.statusBarView?.backgroundColor = UIColor.red

         webView.load(myRequest)

    }
}

extension UIApplication {

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

}

0
投票

请将以下行添加到info.plist中,然后才能实现

“查看基于控制器的状态栏外观=否”

并将以下代码段添加到您的代码中并查看输出

        UIApplication.shared.statusBarStyle = .lightContent
        UIApplication.shared.statusBarStyle = .default

129
投票

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

 override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

如果您有条件地设置此项,则需要调用setNeedsStatusBarAppearanceUpdate(),以便在准备好后对其进行动画处理


-1
投票

斯威夫特3

要在应用程序中设置相同的导航栏外观,可以在AppDelegate.swift中执行此操作:

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

        setupNavigationBarAppearence()
        return true
    }



private func setupNavigationBarAppearence(){
        let navigationBarAppearace = UINavigationBar.appearance()
        navigationBarAppearace.isTranslucent = false
        //nav bar color
        navigationBarAppearace.barTintColor = UIColor.primaryColor()
        //SETS navbar title string to white
        navigationBarAppearace.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
        //Makes the batery icon an any other icon of the device to white.
        navigationBarAppearace.barStyle = .black
    }

99
投票

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

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

当我习惯每个视图控制器,但这工作:

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

26
投票

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

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

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

这段代码:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

不适用于UIViewControllers中包含的UINavigationController,因为编译器会查找statusBarStyleUINavigationController,而不是statusBarStyle包含的ViewControllers

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


25
投票

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

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

在你的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

根据要求改变backgroundColorstatusBarStyle


24
投票

如果要在视图出现后随时更改状态栏样式,可以使用以下命令:

  • 在文件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 } }

13
投票

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

  1. 在info.plist中创建一个新条目“查看基于控制器的状态栏外观”将其设置为“YES”。
  2. 转到故事板,然后选择要更改的导航控制器。单击Storyboard文档大纲部分的导航栏(故事板上的左侧面板)
  3. 转到右侧面板,然后单击属性部分
  4. 在导航栏部分下,您将看到样式。选择您想要的样式(默认为黑色,黑色为白色)

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

enter image description here

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


8
投票

第一步,您需要添加一行密钥:View controller-based status bar appearance和值NOInfo.plist文件。之后,在控制器中添加2个功能,只有控制器才能生效:

override func viewWillAppear(_ animated: Bool) {
       super.viewWillAppear(animated)
       UIApplication.shared.statusBarStyle = .lightContent
}

override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        UIApplication.shared.statusBarStyle = .default    
}
© www.soinside.com 2019 - 2024. All rights reserved.