UIStatusBarStyle PreferredStatusBarStyle在iOS 7上不起作用
在我的iPhone应用程序构build与Xcode 5的iOS 7我设置UIViewControllerBasedStatusBarAppearance=YES
在info.plist
,并在我的ViewController
我有这样的代码:
-(UIStatusBarStyle) preferredStatusBarStyle { return UIStatusBarStyleLightContent; }
但是状态栏在黑色背景下仍然是黑色的。
我知道可以通过在info.plist
设置UIViewControllerBasedStatusBarAppearance=NO
来改变这个应用程序的范围,但是我实际上需要在运行时通过viewController
基础来改变viewController
。
我发现,如果你的ViewController是在一个navigationController里面,那么navigationController的navigationBar.barStyle
决定了statusBarStyle。
将导航条的barStyle
设置为UIBarStyleBlackTranslucent
会给出白色的状态栏文本(即UIStatusBarStyleLightContent
),而UIBarStyleDefault
会给出黑色的状态栏文本(即UIStatusBarStyleDefault
)。
请注意 ,即使您通过barTintColor
完全更改navigationBar的颜色,也barTintColor
。
好的,这是诀窍。 您必须添加键“查看基于控制器的状态栏”,并将值设置为否。
这与此键的含义相反,但即使将该值设置为No
,仍然可以更改状态栏的外观以及是否显示在任何视图控制器中。 所以它的行为是“是”,但是设置为“否”!
现在我可以得到状态栏白色或黑暗。
我可能会迟到一点,但是别的什么人都在寻找一个工作和validation的应用程序广泛的解决scheme。
@mxcl在描述发生这种情况时是正确的。 为了纠正它,我们只需创build一个覆盖UINavigationController的preferredSatusBarStyle()方法的扩展(或obj-c中的类别)。 这是Swift中的一个例子:
extension UINavigationController { public override func preferredStatusBarStyle() -> UIStatusBarStyle { if let rootViewController = self.viewControllers.first { return rootViewController.preferredStatusBarStyle() } return super.preferredStatusBarStyle() } }
这段代码简单地提取第一个视图控制器(根视图控制器)并解开它(obj-c只是检查它不是零)。 如果解包成功(而不是零),那么我们抓住rootViewControllers preferredStatusBarStyle。 否则,我们只是返回默认值。
希望这可以帮助任何人可能需要它。
对于preferredStatusBarStyle()
在UINavigationController
和UITabBarController
工作,我添加下面的代码,它将从当前可见的视图控制器中获得首选的状态栏样式。
extension UITabBarController { public override func childViewControllerForStatusBarStyle() -> UIViewController? { return selectedViewController } } extension UINavigationController { public override func childViewControllerForStatusBarStyle() -> UIViewController? { return visibleViewController } }
对于Swift 3来说,这些不是方法,而是属性:
extension UITabBarController { open override var childViewControllerForStatusBarStyle: UIViewController? { return selectedViewController } } extension UINavigationController { open override var childViewControllerForStatusBarStyle: UIViewController? { return visibleViewController } }
为了在接受的答案中提供更多的细节,在你的应用程序委托的didFinishLaunchingWithOptions:
方法中放入以下行:
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
然后,在Info.plist中,添加View controller-based status bar appearance
,并将其设置为NO
。
我相信这是应该如何做,而不是从导航控制器,如果你想为整个应用程序相同的状态栏颜色。 你可能有不一定embedded到UINavigationController
屏幕,或者其他地方的不同的UINavigationController
子类以及其他东西。
编辑 :你也可以做到这一点,而无需键入任何代码: https : //stackoverflow.com/a/18732865/855680
在viewDidLoad中只写这个
[self setNeedsStatusBarAppearanceUpdate];
只要这样做,它会工作
你可以试试这个吗?
Set UIViewControllerBasedStatusBarAppearance to NO. Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
还有一件事我看到你的问题,你已经写了这样的方法
-(void)UIStatusBarStyle PreferredStatusBarStyle () { return UIStatusBarStyle.LightContent; }
但应该是这样的
-(UIStatusBarStyle)preferredStatusBarStyle{ return UIStatusBarStyleLightContent; }
这是我如何解决它。 通常navigationController或tabBarController是决定状态栏的外观(隐藏,颜色等)。
所以我结束了inheritance导航控制器和覆盖preferredStatusBarStyle。 如果当前可见的ViewContorller实现了StatusBarStyleHandler,我要求将该值用作样式,如果不是,我只是返回一个默认值。
触发状态栏外观更新的方法是调用setNeedsStatusBarAppearanceUpdate
,它将再次触发preferredStatusBarStyle
,并根据方法返回的内容更新UI
public protocol StatusBarStyleHandler { var preferredStatusBarStyle: UIStatusBarStyle { get } } public class CustomNavigationCotnroller: UINavigationController { public override var preferredStatusBarStyle: UIStatusBarStyle { if let statusBarHandler = visibleViewController as? StatusBarStyleHandler { return statusBarHandler.preferredStatusBarStyle } return .default } }
然后用法
public class SomeController: UIViewController, StatusBarStyleHandler { private var statusBarToggle = true // just a sample for toggling the status bar style each time method is called private func toggleStatusBarColor() { statusBarToggle = !statusBarToggle setNeedsStatusBarAppearanceUpdate() } public override var preferredStatusBarStyle: UIStatusBarStyle { return statusBarToggle ? .lightContent : .default } }
1)整个项目的一个设置:
如果可用,请从您的info.plist中移除UIViewControllerBasedStatusBarAppearance
键值对,或者将其设置为NO
而不移除它。 如果它不在你的info.plist中,请不要做任何事情。 该属性的默认值是NO
。
将以下代码添加到您的AppDelegate.m中:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; }
2)不同视图控制器的不同设置:
将UIViewControllerBasedStatusBarAppearance
键值对添加到您的info.plist并将其设置为YES
。
如果View Controller未embedded到导航控制器中。 我们说MyViewController。 只需将下面的代码添加到您的MyViewController.m文件。 如果您的View Controllerembedded到导航控制器中,请创build一个新的Cocoa Touch类并将其设置为UINavigationController的子类。 比方说,MyNC。 在右侧窗格的“故事板”上select“导航控制器视图”; 实用程序 – >身份检查器 – >自定义类 – >类,键入“MyNC”。 链接Storyboard视图和你的“MyNC”Cocoa Touch Class之后,将下面的代码添加到你的MyNC.m中:
- (BOOL)prefersStatusBarHidden { return NO; } -(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; }
如果想要在splashScreen中隐藏statusBar,但想要将样式更改为浅色内容(Plist上的StatusBarInitiallyHidden必须为NO才能隐藏状态栏),则可以将此添加到appDelegate的didFinishLaunchingWithOptions方法以更改为lightContent。
[[UIApplication sharedApplication]setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide]; [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
迅速的例子
在AppDelegate.swift中
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent; return true }
在info.plist中查看基于控制器的状态栏外观:NO
如果您正在使用NavigationController
,则可以inheritanceNavigationController
以便查阅其子视图控制器
// MyCustomNavigationController
- (NSUInteger)supportedInterfaceOrientations { UIViewController *viewControllerToAsk = [self findChildVC]; return [viewControllerToAsk supportedInterfaceOrientations]; } - (BOOL)shouldAutorotate { UIViewController *viewControllerToAsk = [self findChildVC]; return [viewControllerToAsk shouldAutorotate]; } - (UIStatusBarStyle)preferredStatusBarStyle { UIViewController *viewControllerToAsk = [self findChildVC]; return [viewControllerToAsk preferredStatusBarStyle]; } - (UIViewController *)findChildVC { return self.viewControllers.firstObject; }
即使在这里所有的答案,我仍然没有find确切的解决scheme,但从丹尼尔的答案开始。 结果是:
override var preferredStatusBarStyle: UIStatusBarStyle { return visibleViewController?.preferredStatusBarStyle ?? .lightContent }
在导航控制器(类似的选项卡,只是selectedViewController)。 然后它会尊重:
override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
在每个视图控制器中,除非您另行设置。 我不需要在任何地方调用setNeedsStatusBarAppearanceUpdate()
,它只是当你到达每个视图控制器时更新。
您可以设置状态栏的样式。 它将类似IOS 6和以下的状态栏。
将这些方法粘贴到视图控制器中
-(UIStatusBarStyle)preferredStatusBarStyle{ return UIStatusBarStyleBlackOpaque; }
并从视图调用这个方法加载这样的
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) { [self setNeedsStatusBarAppearanceUpdate]; }
对于swift 3,在你的UIViewController中:
override var preferredStatusBarStyle : UIStatusBarStyle { return UIStatusBarStyle.lightContent }