我跟着this thread覆盖了-preferredStatusBarStyle
,但是没有调用它。
我可以更改任何选项以启用它吗? (我在我的项目中使用了XIB。)
答案 0 :(得分:971)
对于使用UINavigationController的任何人:
UINavigationController
不会转发preferredStatusBarStyle
对其子视图控制器的调用。相反,它管理自己的状态 - 正如它应该的那样,它绘制在状态栏所在的屏幕顶部,因此应该负责它。因此,在导航控制器中的VC中实施preferredStatusBarStyle
将不会做任何事情 - 它们永远不会被调用。
诀窍是UINavigationController
用来决定UIStatusBarStyleDefault
或UIStatusBarStyleLightContent
的回报。它基于UINavigationBar.barStyle
。默认值(UIBarStyleDefault
)会生成暗前景UIStatusBarStyleDefault
状态栏。 UIBarStyleBlack
会提供UIStatusBarStyleLightContent
状态栏。
<强> TL; DR:强>
如果您希望UIStatusBarStyleLightContent
使用UINavigationController
:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
答案 1 :(得分:113)
我遇到了同样的问题,并且发现它正在发生,因为我没有在我的应用程序窗口中设置根视图控制器。
我在UIViewController
中实施的preferredStatusBarStyle
用于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;
}
或者,您可以根据背景颜色,在每个视图控制器中根据需要调用以下方法之一,而不必使用setNeedsStatusBarAppearanceUpdate
:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
或
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
请注意,如果您使用此方法,还需要在plist文件中将UIViewControllerBasedStatusBarAppearance
设置为NO
。
答案 2 :(得分:95)
所以我实际上在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 NOT 将“基于控制器的状态栏外观视图”设置为NO。删除该行或将其设置为YES(我认为现在是iOS 7的默认值?)
答案 3 :(得分:60)
对于仍在努力解决这个问题的人来说,swift中的这个简单扩展应该可以帮到你解决问题。
extension UINavigationController {
override open var childViewControllerForStatusBarStyle: UIViewController? {
return self.topViewController
}
}
答案 4 :(得分:15)
Tyson的答案在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;
}
答案 5 :(得分:11)
我的应用使用了全部三个:UINavigationController
,UISplitViewController
,UITabBarController
,因此这些似乎都控制了状态栏并导致preferedStatusBarStyle
无法被调用为了他们的孩子。要覆盖此行为,您可以像其他提到的答案一样创建扩展。这是Swift 4中所有三个的扩展。希望Apple更清楚这种东西。
extension UINavigationController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.topViewController
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.childViewControllers.first
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.childViewControllers.first
}
}
extension UISplitViewController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.childViewControllers.first
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.childViewControllers.first
}
}
编辑:Swift 4.2 API更新的更新
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return self.topViewController
}
open override var childForStatusBarHidden: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return self.children.first
}
open override var childForStatusBarHidden: UIViewController? {
return self.children.first
}
}
extension UISplitViewController {
open override var childForStatusBarStyle: UIViewController? {
return self.children.first
}
open override var childForStatusBarHidden: UIViewController? {
return self.children.first
}
}
答案 6 :(得分:9)
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
该解决方案可能比转换为即将弃用的行为更好。
答案 7 :(得分:8)
在UINavigationController上,未调用preferredStatusBarStyle
,因为topViewController
优先于self
。因此,要在UINavigationController上调用preferredStatusBarStyle
,您需要更改其childViewControllerForStatusBarStyle
。
为一个UINavigationController执行此操作(我的建议):
class MyRootNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
为所有UINavigationController执行此操作(警告:它会影响UIDocumentPickerViewController,UIImagePickerController等):
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
open override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
答案 8 :(得分:7)
vars
。因此UINavigationController
扩展代码应为:
override open var childViewControllerForStatusBarStyle: UIViewController? {
return topViewController
}
override open var childViewControllerForStatusBarHidden: UIViewController? {
return topViewController
}
然后在应该指示状态栏样式的视图控制器中:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
答案 9 :(得分:5)
如果你的viewController在UINavigationController下。
UINavigationController子类并添加
override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}
将调用ViewController&#39; preferredStatusBarStyle
。
答案 10 :(得分:4)
iOS 7中的UIStatusBarStyle
iOS 7中的状态栏是透明的,后面的视图显示为。
状态栏的样式是指其内容的外观。在iOS 7中,状态栏内容为深色(UIStatusBarStyleDefault
)或浅色(UIStatusBarStyleLightContent
)。 iOS 7.0中不推荐使用UIStatusBarStyleBlackTranslucent
和UIStatusBarStyleBlackOpaque
。请改用UIStatusBarStyleLightContent
。
如何更改UIStatusBarStyle
如果状态栏下方是导航栏,状态栏样式将调整为与导航栏样式(UINavigationBar.barStyle
)匹配:
具体来说,如果导航栏样式为UIBarStyleDefault,则状态栏样式为UIStatusBarStyleDefault
;如果导航栏样式为UIBarStyleBlack
,则状态栏样式为UIStatusBarStyleLightContent
。
如果状态栏下方没有导航栏,则应用程序运行时,各个视图控制器可以控制和更改状态栏样式。
- [UIViewController preferredStatusBarStyle]
是在iOS 7中添加的新方法。可以覆盖它以返回首选状态栏样式:
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
如果状态栏样式应由子视图控制器而不是self控制,则覆盖-[UIViewController childViewControllerForStatusBarStyle]
以返回该子视图控制器。
如果您希望选择不使用此行为并使用-[UIApplication statusBarStyle]
方法设置状态栏样式,请将UIViewControllerBasedStatusBarAppearance
键添加到应用的Info.plist
文件并为其指定值NO。
答案 11 :(得分:4)
如果有人使用导航控制器并希望他们所有的导航控制器都具有黑色风格,你可以在Swift 3中编写一个UINavigationController的扩展,它将适用于所有导航控制器(而不是将其分配给一个控制器一次)。
extension UINavigationController {
override open func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.barStyle = UIBarStyle.black
}
}
答案 12 :(得分:3)
除了serenn的回答外,如果要为视图控制器提供一个modalPresentationStyle
(例如.overCurrentContext
),还应该在新显示的视图控制器上调用它:
presentedViewController.modalPresentationCapturesStatusBarAppearance = true
别忘了还要在显示的视图控制器中覆盖preferredStatusBarStyle
。
答案 13 :(得分:3)
如selected answer中所述,根本原因是检查窗口的根视图控制器对象。
l = [('A', 'B'),('C', 'B'),('J', 'K'),('E','D'),('X','B')]
G=nx.Graph()
G.add_edges_from(l)
cc = list(nx.connected_components(G))
component = next(i for i in cc if ('A') in i)
#{'B', 'X', 'C', 'A'}
for x in l:
if x[0] in component or x[1] in component:
print (x)
>>> ('A', 'B')
>>> ('C', 'B')
>>> ('X', 'B')
使用以下扩展名,可以处理以上所有情况-
childForStatusBarStyle
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return selectedViewController?.childForStatusBarStyle ?? selectedViewController
}
}
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return topViewController?.childForStatusBarStyle ?? topViewController
}
}
extension AppRootViewController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return children.first { $0.childForStatusBarStyle != nil }?.childForStatusBarStyle?.preferredStatusBarStyle ?? .default
}
}
键入UIViewControllerBasedStatusBarAppearance
如果以模态方式呈现新流程,则它将与现有状态栏样式流程分离。因此,假设您要展示一个info.plist
,然后向NewFlowUIViewController
添加新的导航或tabBar控制器,然后添加NewFlowUIViewController
的扩展名,以管理其他视图控制器的状态栏样式。
如果在模态显示时设置了{strong> modalPresentationStyle 而不是NewFlowUIViewController
,则必须将fullScreen
设置为true,以便所显示的视图控制器必须接收状态栏外观控件
答案 14 :(得分:1)
Swift 3 iOS 10解决方案:
raise ImproperlyConfigured("Error loading either pysqlite2 or sqlite3 modules (tried in that order): %s" % exc)
django.core.exceptions.ImproperlyConfigured: Error loading either pysqlite2 or sqlite3 modules (tried in that order): No module named '_sqlite3'
答案 15 :(得分:1)
就我而言,我不小心将视图/导航控制器显示为UIModalPresentationStyle.overFullScreen
,这导致preferredStatusBarStyle
未被调用。将其切换回UIModalPresentationStyle.fullScreen
后,一切正常。
答案 16 :(得分:1)
UINavigationController
是UIViewController
(谁知道?)的子类!
因此,当展示嵌入在导航控制器中的视图控制器时,并不是真正展示嵌入的视图控制器;您正在展示导航控制器! UINavigationController
作为UIViewController
的子类,继承了preferredStatusBarStyle
和childForStatusBarStyle
,您可以根据需要设置它们。
以下任何一种方法都可以使用:
info.plist
中,添加以下属性:
UIUserInterfaceStyle
(又称“用户界面样式”) 在preferredStatusBarStyle
内覆盖UINavigationController
preferredStatusBarStyle
(doc)-视图控制器的首选状态栏样式子类或扩展UINavigationController
class MyNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
.lightContent
}
}
OR
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
.lightContent
}
}
在childForStatusBarStyle
内覆盖UINavigationController
childForStatusBarStyle
(doc)-在系统需要视图控制器用于确定状态栏样式时调用“如果容器视图控制器从其子视图控制器之一派生其状态栏样式,请[重写此属性]并返回该子视图控制器。如果返回nil或不重写此方法,则状态栏样式为使用self。如果此方法的返回值发生变化,请调用setNeedsStatusBarAppearanceUpdate()方法。“
子类或扩展UINavigationController
class MyNavigationController: UINavigationController {
override var childForStatusBarStyle: UIViewController? {
topViewController
}
}
OR
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
topViewController
}
}
您可以返回上面想要的任何视图控制器。我推荐以下之一:
注意:如果您决定继承UINavigationController
的子类,请记住通过IB中的身份检查器将该类应用于您的导航控制器。
P.S。我的代码使用Swift 5.1语法?
答案 17 :(得分:1)
对于iOS 13.4,preferredStatusBarStyle
类别中的UINavigationController
方法将不会被调用,izz绕似乎是唯一无需使用子类的选择。
示例:
类别标题:
@interface UINavigationController (StatusBarStyle)
+ (void)setUseLightStatusBarStyle;
@end
实施:
#import "UINavigationController+StatusBarStyle.h"
#import <objc/runtime.h>
@implementation UINavigationController (StatusBarStyle)
void (^swizzle)(Class, SEL, SEL) = ^(Class c, SEL orig, SEL new){
Method origMethod = class_getInstanceMethod(c, orig);
Method newMethod = class_getInstanceMethod(c, new);
if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
else
method_exchangeImplementations(origMethod, newMethod);
};
+ (void)setUseLightStatusBarStyle {
swizzle(self.class, @selector(preferredStatusBarStyle), @selector(_light_preferredStatusBarStyle));
}
- (UIStatusBarStyle)_light_preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
@end
在AppDelegate.h中的用法:
#import "UINavigationController+StatusBarStyle.h"
[UINavigationController setUseLightStatusBarStyle];
答案 18 :(得分:0)
从Xcode 11.4开始,覆盖UINavigationController扩展中的preferredStatusBarStyle
属性不再起作用,因为它将不会被调用。
将barStyle
的{{1}}设置为navigationBar
确实可以,但是如果将子视图添加到navigationBar中,则在明暗模式下外观可能会有所不同,这会增加不必要的副作用。因为通过将.black
设置为黑色,所以嵌入在navigationBar中的视图的barStyle
将始终具有userInterfaceStyle
,而与应用程序的userInterfaceStyle.dark
无关。
我想出的正确解决方案是添加userInterfaceStyle
的子类并在那里覆盖UINavigationController
。如果您随后将此自定义UINavigationController用于所有视图,则将处于保存状态。
答案 19 :(得分:0)
大多数答案并不包括rabbitmqctl set_permissions -p app username '.*' '.*' '.*'
的{{1}}方法的良好实现。根据我的经验,您应该处理诸如在导航控制器上显示透明视图控制器的情况。在这种情况下,您应该将控制权传递给模态控制器(childViewControllerForStatusBarStyle
),但不要在其消失时传递。
UINavigationController
答案 20 :(得分:0)
请注意,使用self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
解决方案时
请务必转到您的plist并将“查看基于控制器的状态栏外观”设置为YES。如果它不,它将无法正常工作。
答案 21 :(得分:0)
在Swift中用于任何类型的UIViewController:
在AppDelegate
集中:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window!.rootViewController = myRootController
return true
}
myRootController
可以是任何类型的UIViewController
,例如UITabBarController
或UINavigationController
。
然后,像这样重写这个根控制器:
class RootController: UIViewController {
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
}
这将改变整个应用程序中状态栏的外观,因为根控制器全权负责状态栏的外观。
请务必在View controller-based status bar appearance
中将属性Info.plist
设置为YES以使其正常工作(这是默认设置)。
答案 22 :(得分:0)
如果有人使用UISearchController遇到此问题。 只需创建一个新的UISearchController子类,然后将下面的代码添加到该类中:
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
答案 23 :(得分:0)
这是解决这个问题的方法。
定义名为 AGViewControllerAppearance 的协议。
<强> AGViewControllerAppearance.h 强>
#import <Foundation/Foundation.h>
@protocol AGViewControllerAppearance <NSObject>
@optional
- (BOOL)showsStatusBar;
- (BOOL)animatesStatusBarVisibility;
- (UIStatusBarStyle)preferredStatusBarStyle;
- (UIStatusBarAnimation)prefferedStatusBarAnimation;
@end
在 UIViewController 上定义一个名为升级的类别。
<强>的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
当然,您可以从协议和 UIViewController实现其余方法( showsStatusBar , animatesStatusBarVisibility , prefferedStatusBarAnimation ) +升级将做到正确 根据他们提供的值进行自定义。
答案 24 :(得分:-2)
NavigationController或TabBarController是需要提供样式的人。以下是我的解决方法:https://stackoverflow.com/a/39072526/242769