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

我使用的是Xcode 8.0 beta 4。

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

public func preferredStatusBarStyle() -> UIStatusBarStyle

然而,我发现它在Swift 3中变成了“Get ONLY变量”。

public var preferredStatusBarStyle: UIStatusBarStyle { get }

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

234676 次浏览

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

 override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}

如果你有条件地设置这个值,你需要调用setNeedsStatusBarAppearanceUpdate(),这样当你准备好时,它就会动画化变化

这对我很有效

在plist中将View controller-based status bar外观设置为没有,然后在UIViewControllerviewDidAppear刚刚添加了以下一行

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

[更新]Xcode 10+ &斯威夫特4.2 +

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

在应用程序的Info.plist中,将View controller-based status bar appearance设置为YES

在你的每个视图控制器中重写preferredStatusBarStyle (苹果公司的文档)。例如:

override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}

如果你有preferredStatusBarStyle返回不同的首选状态栏样式,基于你的视图控制器内部的某些变化(例如,滚动位置或显示的图像是否暗),那么当状态改变时,你会想要调用setNeedsStatusBarAppearanceUpdate()

ios7之前的版本,已弃用的方法

苹果对此表示反对,所以它将在未来被删除。使用上面的方法,这样你就不必在下一个iOS版本发布时重写它。

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

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

UIApplication.shared.statusBarStyle = .lightContent

导航控制器

如果你使用导航控制器,并且你想要使用每个视图控制器的首选状态栏样式,并在应用程序的info.plist中将View controller-based status bar appearance设置为YES

extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}
}
< p > Swift 3 &4、iOS 10 &11、Xcode 9 &10 < br > 对我来说,这个方法不起作用:

override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}

当我习惯了每个视图控制器,但这是有效的:

  • 在文件信息。列表,添加行:View controller-based status bar appearance并设置为NO

  • appdelegate中的Next:

    UIApplication.shared.statusBarStyle = .lightContent
    

如果你想在视图出现后随时改变状态栏的样式,你可以使用这个:

  • 在文件信息。list add row: 查看基于控制器的状态栏外观并将其设置为是的

    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.plist文件中添加一行,键为View controller-based status bar appearance,值为NO。在这之后,在你的控制器中添加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
}

如果你想将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
}

适用于UINavigationController中包含的UIViewControllers,因为编译器查找的是UINavigationControllerstatusBarStyle,而不是它所包含的ViewControllersstatusBarStyle

希望这能帮助那些没有成功回答这个公认答案的人!

您需要在您的信息中添加以下关键字。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

Xcode 8.3.1, Swift 3.1

  1. 在info中创建一个新条目。plist“基于视图控制器的状态栏外观”设置为“NO”。

  2. 打开AppDelegate.swift,在"didFinishLaunchingWithOptions"方法中添加这些行:

应用程序。statusBarStyle = .lightContent

斯威夫特3

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

然后使用这个扩展为所有NavigationController

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

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

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

你也可以在故事板中这样做

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

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

enter image description here

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

斯威夫特3

在信息。plist添加一行名为“基于视图控制器的状态栏外观”,并将其值设置为No

class YourViewController: UIViewController {


override func viewDidLoad() {
super.viewDidLoad()


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


}


}

斯威夫特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
}

对于objective C,只需在应用程序didFinishLaunch方法中添加这一行

UIApplication.sharedApplication.statusBarStyle = UIStatusBarStyleLightContent;
< p > 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
}

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

对于任何愿意理解过去几年出现的不同方法背后的逻辑的人来说,这篇文章都是完整的。同时,从Xcode 10, Swift 4.2开始,第一次接近不支持和不再受支持(即,如果你试图使用它,不会将生效)。为了更好地理解Plist.info标志和自定义实践背后的原因,仍然会参考您的信息。

重要的澄清

理解定制状态栏外观的两种方法非常重要。它们是不同的,不应该混在一起。

第一种方法-整个应用程序只有一种颜色(iOS7已弃用)

在信息。请列出您找到或创建一个键称为

View controller-based status bar appearance

并将其设置为没有

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

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

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

这样你就不需要在每个视图控制器上重新建立这个设置。但是,您总是可以采用这种方法来自动改变外观。

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

这是相反的。要使它工作,请继续到信息。Plist和set

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)并遵循上面的说明。


奖金

基于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")
}
}
}

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

如果你想让.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

当条样式为黑色时,它将侦听您重写的变量。希望这能帮助到一些人:)

斯威夫特4 +

对于白色状态栏文本:

navigationController.navigationBar.barStyle = .blackTranslucent

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
}

你可以使用一个名为“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
})
}
}

下面是关于状态栏样式更改的苹果公司的指导方针/指令

如果你想设置状态栏样式,应用程序级别,那么在你的.plist文件中将UIViewControllerBasedStatusBarAppearance设置为NO。在你的appdelegate > didFinishLaunchingWithOptions中添加下面的ine(你可以通过编程方式从应用委托中完成)。

Objective - C

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

斯威夫特

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

如果你想在视图控制器级别设置状态栏样式,那么按照以下步骤:

  1. 如果你只需要在UIViewController级别设置状态栏样式,在.plist文件中将UIViewControllerBasedStatusBarAppearance设置为YES
  2. 在viewDidLoad中添加函数- setNeedsStatusBarAppearanceUpdate

  3. 重写视图控制器中的preferredStatusBarStyle。

Objective - 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的值。

enter image description here

使用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
}


}

大多数答案都是相同的内容,但当我使用深色背景时,它们都没有真正解决启动屏幕的问题。

我在info.plist中使用以下方法解决了这个问题,它产生了一个轻样式的状态栏。

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

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

1)信息。plist添加:

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

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

如果你只想改变一个视图控制器的状态栏,在viewDidLoad上添加:

2.1) Info.plist

基于控制器的状态栏外观->是

2.2)

override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}

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

1)信息。plist添加:

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

2) AppDelegate -> didFinishLaunchingWithOptions

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

改变状态栏做不工作尝试做推送(导航控制器),只在呈现模态视图控制器。

为了补充@Krunal https://stackoverflow.com/a/49552326/4697535的精彩回答

如果你正在使用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
}
}
}

如果你收到警告:'statusBarStyle'的Setter在iOS 9.0中已弃用:,那么将状态栏设置为亮或暗使用以下代码:

//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

这不会使你的导航栏改变,它纯粹是指示样式,因此相应地改变状态栏。

NB。你需要确保你在info。plist中进行了设置。

View controller-based status bar appearance to YES

Xcode 10或更高版本

在Swift 5中测试

不需要代码,只需执行以下步骤。

如果你想改变整个应用的状态栏。

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

不要忘记信息。plist变化

  1. 选择信息选项卡
  2. 将此键添加到您的plist文件&;基于视图控制器的状态栏外观&;=没有

运行项目并检查它。

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

如果你使用模态表示,你需要设置:

viewController.modalPresentationCapturesStatusBarAppearance = true

在iOS 13中,你可以使用.darkContent UIStatusBarStyle属性来显示暗状态栏

如果仍然无法更改状态栏样式的基础上的方法

override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}

你可以试试这个方法:

override viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.barStyle = .black
}

斯威夫特5

为了在https://stackoverflow.com/a/40066798/2082851中为PRAVEEN的答案添加更多细节,我想提供我的实现。它支持的灵活性来自定义每个控制器的状态栏。

总的来说,我们将创建一个BaseViewController来处理所有情况下的statusBarStyle属性。当你创建一个新的控制器时,让它成为这个基控制器的子类。

每当您想要更改状态外观时,您只需更新此属性。状态栏样式将立即更新。

实现

class BaseViewController: UIViewController {


var statusBarStyle: UIStatusBarStyle = .default {
didSet {
setNeedsStatusBarAppearanceUpdate()
}
}


override var preferredStatusBarStyle: UIStatusBarStyle {
return statusBarStyle
}
}

演示

class ViewController: BaseViewController, UIScrollViewDelegate {


let scrollView = UIScrollView()
...
func scrollViewDidScroll(_ scrollView: UIScrollView) {
UIView.animate(withDuration: 0.3) {
if scrollView.contentOffset.y > 30 {
self.statusBarStyle = .darkContent
} else {
self.statusBarStyle = .lightContent
}
}
}
}

enter image description here

2. UINavigationController

对于UINavigationController,它是一个特殊情况,你可以遵循以下两种解决方案:

解决方案A:使用消息分派重写

因为UINavigationController是一个NSObject并且继承自ObjectiveC,所以它的方法是message dispatch,你可以重写它们。

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

解决方案B:创建UINavigationController子类

如果你已经有一个自定义的UINavigationController(通常需要控制更多的需求),这对你来说是最好的解决方案。

final class NavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? super.preferredStatusBarStyle
}
}
  1. < p >选择光的内容enter image description here

  2. 查看基于控制器的状态栏外观没有添加到.plist enter image description here < / p >

我也在这方面挣扎,所以如果你正在呈现一个FULLSCREEN模态视图控制器,请确保将.modalPresentationStyle设置为.fullscreen,然后,在你的呈现视图控制器上,只需要将.preferredStatusBarStyle重写为.lightContent

所以:

let navigationController = UINavigationController(rootViewController: viewController)
navigationController.modalPresentationStyle = .fullScreen // <=== make sure to set navigation modal presentation style
present(navigationController, animated: true, completion: nil)

在你的自定义视图控制器上,覆盖状态栏样式:

    override var preferredStatusBarStyle: UIStatusBarStyle {
.lightContent
}