我正在使用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中使用的样式?
Answers:
这是iOS 7及更高版本的首选方法
在您的应用程序中Info.plist
,将设置View controller-based status bar appearance
为YES
。
在每个视图控制器中覆盖preferredStatusBarStyle
(Apple文档)。例如:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
如果preferredStatusBarStyle
根据视图控制器内部发生的更改返回了不同的首选状态栏样式(例如,滚动位置或显示的图像是否为暗),则需要setNeedsStatusBarAppearanceUpdate()
在状态更改时调用。
iOS 7之前的版本,不建议使用的方法
苹果已弃用此功能,因此将来会删除它。使用上述方法,以便在下一个iOS版本发布时不必重写它。
如果您的应用程序将支持在您的应用程序中Info.plist
,请设置View controller-based status bar appearance
为NO
。
在appDelegate.swift
的didFinishLaunchingWithOptions
功能,加上:
UIApplication.shared.statusBarStyle = .lightContent
对于导航控制器
如果您使用导航控制器,并且希望使用每个视图控制器的首选状态栏样式并将其设置View controller-based status bar appearance
为YES
应用程序的info.plist
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
到是
这样,每当打开一个新的视图控制器时,如果在每个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。您可以statusBar
使用KVC 获取对象并设置其背景颜色。您通过这种方式获得的对象是UIStatusBar
,它是从派生的UIView
,因此自然支持backgroundColor
属性。这是肮脏的,不是合法的方法,但是到目前为止,这是为状态栏设置自定义颜色的唯一方法(不考虑UINavigationBar
允许完全自定义navbar + statusbar外观的方法)。这很可能导致您的应用被拒绝。但是也许你很幸运。而且,如果您是在某些复杂的情况下(例如嵌套的层次结构,子导航和视图控制器),那么这可能是自定义状态栏外观的唯一方式,或者至少是较为麻烦的方式(例如,使其透明化)
Xcode 10 +,Swift 4.2
别无选择:开发人员应让每个视图控制器定义状态栏外观,方法是将标志设置为YES(或省略此操作,因为默认情况下为YES)并遵循上述说明。
奖金
您可以(尽管不鼓励)在复杂情况下使用基于Hack的解决方案,以便在任何阶段自愿更改statusbar的外观。在颜色方面,以下扩展方法完全可以完成常规方法所能完成的工作。您可以根据需要进行调整。
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
和它一起走,那就会坚持下去。
Swift 3&4,iOS 10&11,Xcode 9&10
对我来说,这种方法不起作用:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
当我习惯于每个视图控制器时,但这有效:
在文件info.list中,添加row:View controller-based status bar appearance
并设置为NO
appdelegate中的下一个:
UIApplication.shared.statusBarStyle = .lightContent
如果您要将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
为,因为编译器外观statusBarStyle
的UINavigationController
的,不statusBarStyle
的ViewControllers
被它包含。
希望这对尚未成功接受答案的人有所帮助!
如果要在视图出现后随时更改状态栏样式,可以使用以下方法:
在文件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
}
}
If you call this method within an animation block, the changes are animated along with the rest of the animation block.
您需要在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
更改backgroundColor
并statusBarStyle
根据要求。
如果要在整个应用程序中更改状态栏。
不要忘记info.plist的更改
运行您的项目并检查它。
我在Swift 5和Xcode 10.2&11.0中的项目
您也可以在情节提要中执行此操作
您将必须为每个导航控制器执行此操作。但是,该导航控制器下的任何视图都会将所有视图状态栏的样式/颜色更改为您刚刚选择的样式/颜色。我发现此选项更好,因为您可以立即看到结果,而不必在每个视图控制器中添加额外的代码行。
(在所有Swift项目中使用Xcode 8.3.3完成)
View controller-based status bar appearance = NO
在整个应用程序中仅设置且仅使用浅色或深色样式的方法。可惜的是,这种“无代码”方式仅在导航控制器中有效,Apple应该考虑在任何View Controller实例内添加另一个字段来设置此选项。
对于希望在以下平台上更改所有视图控制器状态栏的用户:iOS 11,Swfit 4/5解决方案非常简单。
1) Info.plist添加:
查看基于控制器的状态栏外观->否
2) XCode slect项目的左侧> 目标 >选择项目>在常规下>部署信息>选择状态栏样式:浅
如果只想更改一个viewcontroller的状态栏,请在viewDidLoad上添加:
2.1)Info.plist
查看基于控制器的状态栏外观->是
2.2)
override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}
从App代表更改的Objective-C(或本机反应):
1) Info.plist添加:
查看基于控制器的状态栏外观->否
2) AppDelegate-> didFinishLaunchingWithOptions
[[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDarkContent animated:YES];
更改状态栏仅在呈现模态视图控制器时才尝试执行push(导航控制器)不起作用。
第一步,你需要添加与键的一行:View controller-based status bar appearance
和值NO
到Info.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
}
处理导航栏时,状态栏文本颜色似乎有一个小问题。
如果您希望将.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
当条形样式为黑色时,它会监听您的覆盖变量。希望这可以帮助某人:)
这是有关状态栏样式更改的Apple准则/说明。
如果要设置状态栏样式,请在文件中将应用程序级别设置UIViewControllerBasedStatusBarAppearance
为。并在您的>中添加以下ine(可以通过应用程序委托执行此操作)。NO
.plist
appdelegate
didFinishLaunchingWithOptions
目标C
[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
迅速
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
application.statusBarStyle = .lightContent
return true
}
如果要设置状态栏样式,请在视图控制器级别执行以下步骤:
UIViewControllerBasedStatusBarAppearance
到YES
中.plist
文件,如果需要设置状态栏样式仅UIViewController的水平。在viewDidLoad中添加功能- setNeedsStatusBarAppearanceUpdate
在您的视图控制器中重写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的值。
通过@Krunal添加到伟大的解决方案中https://stackoverflow.com/a/49552326/4697535
如果您使用UINavigationController
,preferredStatusBarStyle
则不会对起作用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
}
}
}
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
}
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
}
这对我有用
将View controller-based status bar
外观设置为plist中的NO,然后在其中 UIViewController
viewDidAppear
添加以下行
UIApplication.shared.setStatusBarStyle(UIStatusBarStyle.lightContent, animated: true)
迅捷3
如果Info.plist中基于View Controller的状态栏外观= YES
然后将此扩展名用于所有NavigationController
extension UINavigationController
{
override open var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
如果没有UINavigationController而只有UIViewController,则使用以下代码:
extension UIViewController
{
override open var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
要在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
}
}
}
}
UINavigationController
对于UINavigationController
,这是一种特殊情况,您可以采用以下任一解决方案:
由于UINavigationController是NSObject
从继承的ObjectiveC
,其方法是message dispatch
,因此您可以覆盖它们。
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}
}
UINavigationController
子类如果您已经有一个自定义项UINavigationController
(通常需要控制更多需求),那么这是最适合您的解决方案。
final class NavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? super.preferredStatusBarStyle
}
}
您可以使用名为“ shouldStatusBarDark”的布尔属性来切换状态栏颜色。您还可以更新其值,以在滚动时更改状态栏的颜色。
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
})
}
}
这些答案中的大多数都是相同的东西,但是当使用深色背景时,它们实际上都没有为我解决启动屏幕上的问题。
我在以下内容中解决了这一问题,info.plist
并制作了一个样式简单的状态栏。
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
如果收到警告:iOS 9.0中已弃用“ statusBarStyle”的设置器:使用-[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更改为纯粹指示样式,因此不会相应地更改状态栏。
注意 您需要确保在info.plist中进行设置。
View controller-based status bar appearance to YES
在iOS 13中,您可以使用.darkContent
UIStatusBarStyle
属性显示暗状态栏
使用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
}
}