preferredStatusBarStyle不被调用
我跟着这个线程来覆盖-preferredStatusBarStyle
,但它不被调用。 有什么select,我可以改变启用它? (我在我的项目中使用XIB。)
可能的根本原因
我有同样的问题,并发现这是因为我没有在我的应用程序窗口中设置根视图控制器。
我在其中实现了preferredStatusBarStyle
的UIViewController
在UITabBarController
,它控制了屏幕上的视图的外观。
当我设置根视图控制器指向此UITabBarController
,状态栏更改开始正常工作,并按预期方式(并调用preferredStatusBarStyle
方法)。
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // other view controller loading/setup code self.window.rootViewController = rootTabBarController; [self.window makeKeyAndVisible]; return YES; }
替代方法(在iOS 9中弃用)
或者,您可以根据自己的背景颜色,在每个视图控制器中根据需要调用以下其中一种方法,而不必使用setNeedsStatusBarAppearanceUpdate
:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
要么
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
请注意,如果使用此方法,则还需要在plist文件中将UIViewControllerBasedStatusBarAppearance
设置为NO
。
对于任何使用UINavigationController的人:
UINavigationController
不会将preferredStatusBarStyle
调用转发到其子视图控制器。 相反,它pipe理着自己的状态,因为它应该在状态栏所在的屏幕顶部绘制,所以应该对它负责。 因此,在导航控制器内的VC中实现preferredStatusBarStyle
将不会执行任何操作 – 它们将永远不会被调用。
窍门是UINavigationController
用来决定返回什么UIStatusBarStyleDefault
或UIStatusBarStyleLightContent
。 它基于它的UINavigationBar.barStyle
。 默认( UIBarStyleDefault
)导致在黑暗的前景UIStatusBarStyleDefault
状态栏。 而UIBarStyleBlack
将会提供一个UIStatusBarStyleLightContent
状态栏。
TL; DR:
如果您想在UINavigationController
使用UIStatusBarStyleLightContent
,请使用:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
所以我实际上添加了一个类别到UINavigationController,但使用的方法:
-(UIViewController *)childViewControllerForStatusBarStyle; -(UIViewController *)childViewControllerForStatusBarHidden;
并有那些返回当前可见的UIViewController。 这让当前的可见视图控制器设置自己的首选风格/可见性。
这是一个完整的代码片段:
在Swift中:
extension UINavigationController { public override func childViewControllerForStatusBarHidden() -> UIViewController? { return self.topViewController } public override func childViewControllerForStatusBarStyle() -> UIViewController? { return self.topViewController } }
在Objective-C中:
@interface UINavigationController (StatusBarStyle) @end @implementation UINavigationController (StatusBarStyle) -(UIViewController *)childViewControllerForStatusBarStyle { return self.topViewController; } -(UIViewController *)childViewControllerForStatusBarHidden { return self.topViewController; } @end
为了好的措施,下面是在UIViewController中实现的方法:
在Swift中
override public func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } override func prefersStatusBarHidden() -> Bool { return false }
在Objective-C中
-(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; // your own style } - (BOOL)prefersStatusBarHidden { return NO; // your own visibility code }
最后,请确保您的应用程序plist没有将“基于视图控制器的状态栏外观”设置为NO。 删除该行或将其设置为YES(我相信这是iOS 7的默认设置?)
泰森的答案是正确的在UINavigationController
中将状态栏颜色更改为白色。
如果有人希望通过在AppDelegate
编写代码来完成相同的结果,那么使用下面的代码并将其写入AppDelegate's
didFinishLaunchingWithOptions
方法中。
不要忘记在.plist文件中将UIViewControllerBasedStatusBarAppearance
设置为YES
,否则更改将不会反映出来。
码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // status bar appearance code [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack]; return YES; }
对于还在为此而苦恼的人,这个简单的扩展应该可以解决你的问题。
extension UINavigationController { override open var childViewControllerForStatusBarStyle: UIViewController? { return self.topViewController } }
除了Hippo的答案:如果您使用的是UINavigationController,那么最好添加一个类别:
// UINavigationController+StatusBarStyle.h: @interface UINavigationController (StatusBarStyle) @end // UINavigationController+StatusBarStyle.m: @implementation UINavigationController (StatusBarStyle) - (UIStatusBarStyle)preferredStatusBarStyle { //also you may add any fancy condition-based code here return UIStatusBarStyleLightContent; } @end
该解决scheme可能比切换到即将被弃用的行为更好。
如果你的viewController在UINavigationController下。
子类UINavigationController并添加
override var preferredStatusBarStyle: UIStatusBarStyle { return topViewController?.preferredStatusBarStyle ?? .default }
ViewController的preferredStatusBarStyle
将被调用。
UIStatusBarStyle在iOS 7中
iOS 7中的状态栏是透明的,它后面的视图显示了通过。
状态栏的风格是指其内容的外观。 在iOS 7中,状态栏内容可能是黑暗的( UIStatusBarStyleDefault
)或亮的( UIStatusBarStyleLightContent
)。 UIStatusBarStyleBlackTranslucent
和UIStatusBarStyleBlackOpaque
都在iOS 7.0中被弃用。 改用UIStatusBarStyleLightContent
。
如何更改UIStatusBarStyle
如果下面的状态栏是一个导航栏,状态栏风格将被调整为与导航栏风格( UINavigationBar.barStyle
)相匹配:
具体而言,如果导航栏风格是UIBarStyleDefault,则状态栏风格将为UIStatusBarStyleDefault
; 如果导航栏风格是UIBarStyleBlack
,则状态栏风格将是UIStatusBarStyleLightContent
。
如果状态栏下方没有导航栏,则应用程序运行时,可以通过单独的视图控制器来控制和更改状态栏的样式。
– [UIViewController preferredStatusBarStyle]
是在iOS 7中添加的新方法。可以覆盖返回首选状态栏样式:
- (UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; }
如果状态栏风格应该由子视图控制器而不是自我控制,则覆盖-[UIViewController childViewControllerForStatusBarStyle]
返回该子视图控制器。
如果您更愿意select退出此行为,并使用-[UIApplication statusBarStyle]
方法设置状态栏样式,请将UIViewControllerBasedStatusBarAppearance
关键点添加到应用程序的Info.plist
文件中,并将其值设置为NO。
上面的答案对于UINavigationControllers来说仍然是一个很好的答案 。 不过,对于swift 3,childViewController函数已经改变为vars
。 所以UINavigationController
扩展代码应该是:
override open var childViewControllerForStatusBarStyle: UIViewController? { return topViewController } override open var childViewControllerForStatusBarHidden: UIViewController? { return topViewController }
然后在视图控制器应该指定状态栏的风格:
override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
Swift 3 iOS 10解决scheme:
override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
如果有人正在使用导航控制器,并希望所有的导航控制器都具有黑色风格,那么可以在Swift 3中这样写一个扩展到UINavigationController,它将应用于所有导航控制器(而不是将其分配给一个控制器时间)。
extension UINavigationController { override open func viewDidLoad() { super.viewDidLoad() self.navigationBar.barStyle = UIBarStyle.black } }
这是我解决这个问题的方法。
定义一个名为AGViewControllerAppearance的协议。
AGViewControllerAppearance.h
#import <Foundation/Foundation.h> @protocol AGViewControllerAppearance <NSObject> @optional - (BOOL)showsStatusBar; - (BOOL)animatesStatusBarVisibility; - (UIStatusBarStyle)preferredStatusBarStyle; - (UIStatusBarAnimation)prefferedStatusBarAnimation; @end
在UIViewController上定义一个名为Upgrade的类别。
的UIViewController + Upgrade.h
#import <UIKit/UIKit.h> @interface UIViewController (Upgrade) // // Replacements // - (void)upgradedViewWillAppear:(BOOL)animated; @end
的UIViewController + Upgrade.m
#import "UIViewController+Upgrade.h" #import <objc/runtime.h> #import "AGViewControllerAppearance.h" // This is the appearance protocol @implementation UIViewController (Upgrade) + (void)load { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wselector" Method viewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:)); #pragma clang diagnostic pop Method upgradedViewWillAppear = class_getInstanceMethod(self, @selector(upgradedViewWillAppear:)); method_exchangeImplementations(viewWillAppear, upgradedViewWillAppear); } #pragma mark - Implementation - (void)upgradedViewWillAppear:(BOOL)animated { // // Call the original message (it may be a little confusing that we're // calling the 'same' method, but we're actually calling the original one :) ) // [self upgradedViewWillAppear:animated]; // // Implementation // if ([self conformsToProtocol:@protocol(AGViewControllerAppearance)]) { UIViewController <AGViewControllerAppearance> *viewControllerConformingToAppearance = (UIViewController <AGViewControllerAppearance> *)self; // // Status bar // if ([viewControllerConformingToAppearance respondsToSelector:@selector(preferredStatusBarStyle)]) { BOOL shouldAnimate = YES; if ([viewControllerConformingToAppearance respondsToSelector:@selector(animatesStatusBarVisibility)]) { shouldAnimate = [viewControllerConformingToAppearance animatesStatusBarVisibility]; } [[UIApplication sharedApplication] setStatusBarStyle:[viewControllerConformingToAppearance preferredStatusBarStyle] animated:shouldAnimate]; } if ([viewControllerConformingToAppearance respondsToSelector:@selector(showsStatusBar)]) { UIStatusBarAnimation animation = UIStatusBarAnimationSlide; if ([viewControllerConformingToAppearance respondsToSelector:@selector(prefferedStatusBarAnimation)]) { animation = [viewControllerConformingToAppearance prefferedStatusBarAnimation]; } [[UIApplication sharedApplication] setStatusBarHidden:(! [viewControllerConformingToAppearance showsStatusBar]) withAnimation:animation]; } } } @end
现在,该说视图控制器正在实现AGViewControllerAppearance协议。
例:
@interface XYSampleViewController () <AGViewControllerAppearance> ... the rest of the interface @end
当然,你可以从协议中实现其余的方法( showsStatusBar , animatesStatusBarVisibility , prefferedStatusBarAnimation ), UIViewController + Upgrade将根据它们提供的值进行适当的定制。
如果有人遇到这个问题与UISearchController。 只要创build一个UISearchController的新子类,然后将下面的代码添加到该类中:
override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent }
在任何一种UIViewController的Swift中:
在你的AppDelegate
设置:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { window!.rootViewController = myRootController return true }
myRootController
可以是任何types的UIViewController
,例如UITabBarController
或UINavigationController
。
然后,像这样覆盖这个根控制器:
class RootController: UIViewController { override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } }
这将改变整个应用程序状态栏的外观,因为根控制器是唯一负责状态栏的外观。
请记住在Info.plist
中将View controller-based status bar appearance
为YES以使其工作(这是默认设置)。
在UINavigationController上, preferredStatusBarStyle
不被调用,因为它的topViewController
比self
更topViewController
。 所以,为了获得在UINavigationController上调用的preferredStatusBarStyle
,你需要改变它的childViewControllerForStatusBarStyle
。
做一个UINavigationController(我的build议):
class MyRootNavigationController: UINavigationController { override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } override func childViewControllerForStatusBarStyle() -> UIViewController? { return nil } }
为所有UINavigationController(警告:它影响UIDocumentPickerViewController,UIImagePickerController等)做到这一点:
extension UINavigationController { public override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } public override func childViewControllerForStatusBarStyle() -> UIViewController? { return nil } }
NavigationController或TabBarController是需要提供样式的。 这是我解决的方法: https : //stackoverflow.com/a/39072526/242769
注意当使用self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
解
一定要去你的plist,并将“查看基于控制器的状态栏外观”设置为YES。 如果它不,它将无法正常工作。