我正在使用Xcode 8.0 beta 4。
在之前的版本中,UIViewController有方法可以设置状态栏样式。
public func preferredStatusBarStyle() -> UIStatusBarStyle
然而,我发现在Swift 3中它变成了一个 "仅获取变量"。
public var preferredStatusBarStyle: UIStatusBarStyle { get }
我该如何为我的UIViewController提供样式?
我正在使用Xcode 8.0 beta 4。
在之前的版本中,UIViewController有方法可以设置状态栏样式。
public func preferredStatusBarStyle() -> UIStatusBarStyle
然而,我发现在Swift 3中它变成了一个 "仅获取变量"。
public var preferredStatusBarStyle: UIStatusBarStyle { get }
我该如何为我的UIViewController提供样式?
这是iOS 7及更高版本的首选方法
在应用程序的Info.plist
中将View controller-based status bar appearance
设置为YES
。
在每个视图控制器中覆盖preferredStatusBarStyle
(Apple文档)。例如:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
如果您的preferredStatusBarStyle
基于视图控制器内部的某些更改(例如滚动位置或显示的图片是否为深色),返回不同的首选状态栏样式,那么当该状态发生变化时,您将需要调用setNeedsStatusBarAppearanceUpdate()
。
iOS7之前的版本,已弃用的方法。
Apple已将其弃用,因此它将在未来被删除。请使用上述方法,以便在下一个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
}
}
本文旨在供有意识了解过去几年中不同方法背后逻辑的人使用,内容未做任何修改。同时,从 Xcode 10,Swift 4.2 开始,第一种方法已弃用,不再受支持(即使您尝试使用它,也不会生效)。为了更好地理解 Plist.info
标志和自定义实践背后的原因,仍可参考此方法。
非常重要的是要了解两种自定义状态栏外观的方法。它们是不同的,不应混淆使用。
在 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
为YES
这样,每当打开新的视图控制器时,如果您在每个UIViewController
实例中插入此实现,则可以单独设置状态栏样式:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent // .default
}
你可以像第一次设置一样,在状态栏上设置暗色或浅色样式,每个视图控制器都可以单独设置。
UIKit 在两种情况下获取此属性:
setNeedsStatusBarAppearanceUpdate()
时。在后一种情况下,您可以通过以下代码来操纵状态栏外观:
var isDark = false {
didSet {
setNeedsStatusBarAppearanceUpdate()
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return isDark ? .lightContent : .default
}
func toggleAppearance() {
isDark.toggle()
}
那么,每当您调用toggleAppearance()
时,状态栏样式将被触发更改。
有一个黑科技可以直接访问状态栏:
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),并遵循上述说明。
额外内容
基于黑客攻击的解决方案,您可能会(虽然不鼓励)在复杂情况下使用,以便在任何阶段自愿更改状态栏外观。就颜色而言,以下扩展方法正是您可以用常规方法完成的操作。您可以根据需要进行调整。
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")
}
}
}
你可以尝试覆盖返回的值,而不是设置它。该方法被声明为{ get },所以只需提供一个getter:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
如果您按条件设置它,那么在准备好时,您需要调用setNeedsStatusBarAppearanceUpdate()
以便它在动画更改。prefersStatusBarHidden
。如果您选择 UIApplication.shared.statusBarStyle
,那么您将被困在其中。 - superarts.orgSwift 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
如果您想要在整个应用程序中更改状态栏。
不要忘记info.plist的更改
运行项目并检查它。
我的项目在Swift 5和Xcode 10.2 & 11.0中。
UIStatusBarStyle
UIStatusBarStyleLightContent
UIViewControllerBasedStatusBarAppearance
- undefinedUINavigationController
中包含的所有视图的状态栏颜色为白色,请在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
,因为编译器会查找UINavigationController
的statusBarStyle
,而不是其中包含的ViewControllers
的statusBarStyle
。希望这能帮助那些没有成功使用已接受答案的人!
在info.list文件中添加一行:View controller-based status bar appearance并将其设置为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.plist文件中添加以下密钥:
View controller-based status bar appearance
,其布尔值设置为NO
在您的appdelegate类中,在didFinishLaunchingWithOptions
方法中return之前。
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
根据需要更改backgroundColor
和statusBarStyle
。
您也可以在storyboard中完成此操作
您需要为每个导航控制器执行此操作。但是,在该导航控制器下的任何视图都将更改所有视图的状态栏样式/颜色为您刚刚选择的样式。我认为这个选项更好,因为您可以立即查看结果,并且不必在每个视图控制器中添加额外的代码行。
(使用Xcode 8.3.3在全Swift项目中完成)
对于想要在iOS 11上为所有视图控制器更改状态栏的人,Swift 4/5的解决方案非常简单。
1) 在 Info.plist 中添加:
View controller-based status bar appearance -> NO
2) 在 XCode 的左侧选择项目 > Targets > 选择你的项目 > 在“通用”下选择“部署信息” > 选择状态栏样式:浅色。
如果你只想为一个视图控制器更改状态栏,在viewDidLoad中添加:
2.1) Info.plist
View controller-based status bar appearance -> YES
2.2)
override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}
Objective-C(或React Native)从App Delegate更改:
1)在Info.plist中添加:
View controller-based status bar appearance -> NO
2)AppDelegate -> didFinishLaunchingWithOptions
[[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDarkContent animated:YES];
试图使用push(导航控制器)更改状态栏不起作用,只有在呈现模态视图控制器时才起作用。
var preferredStatusBarStyle: UIStatusBarStyle = .lightContent
- Anbu.Karthik