I have problems with colour of text in Status Bar. I want to make colour of text white, but keep black colour on modal views.
I have next configuration:
Storyboard with settings "Opens in 5.1" and "Project Deployment target 7.0" and "View as iOS7 and later"
UITabBarViewController
4 UINavigationControllers
Each navigation controller has custom subclass of UIViewController inside
Background colour of UINavigationBar set to dark via appearance.
View controller-based status bar appearance set to YES
My subclass of UITabBarViewController has next methods:
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setNeedsStatusBarAppearanceUpdate];
}
These methods are called after application started.
I also have same methods calls in my UIViewControllers subclasses:
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent; // This method never called
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setNeedsStatusBarAppearanceUpdate];
}
I also tried to change return value of -preferredStatusBarStyle to UIStatusBarStyleDefault (well, I know that it should paint text in black, but I tried anyway)
Same thing for setting Status Bar option to Light Content in Storyboard. Doesn't work too.
I know there are a lot of questions on SO similar to mine, but proposed solutions doesn't help in my situation.
My status bar still looks like this:
And I want to change its colour to white =/
This is a work around that I occasionally found right now after struggling with this issue for about 2 weeks.
// This is a workaround just enables white text colour in status bar in iOS7, iOS7.1
// Dont touch it until things break
// Despite this category says "draw white", colour automatically becomes black on white background w/o additional code
#interface UINavigationController (StatusBarStyle)
#end
#implementation UINavigationController (StatusBarStyle)
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
#end
// Place at the bottom of your AppDelegate.m
// Magic!
I need to thank people who answered this question, but I already tried these solutions and they didn't help :( This category on UINavigationController just works.
First of all, you say that - (UIStatusBarStyle)preferredStatusBarStyle is never called in your UIViewController subclasses. It's normal. This method is called by your root view controller. In your case, it is the UITabBarViewController.
You also say that you've tried to set Status Bar option to Light Content in Storyboard. If you look closely, you should have done that in a section named Simulated metrics. So as the title suggest, modifications here are simulated...
I suggest you to try to add the key UIViewControllerBasedStatusBarAppearance in your Info.plist and to set it to YES.
You need to set this in your RootViewController :
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
Related
I am trying to change my statusbar style (the color of status bar text, more specifically) depending on which viewController is active through this:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
But that does not work. Rather, it makes the whole navigationBar black (instead of just the statusbar). Neither does the following:
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
But this only seems to work when the viewController is not embedded in a navController (when I hide the navBar, it works!). My viewController hierarchy is the following:
tabBarController -> navigationControllers -> viewController
Also: Setting 'View controller-based status bar appearance' to YES & NO does not make a difference.
I am glad for any help!
You can try following.
keep this to your ViewController
-(UIStatusBarStyle)preferredStatusBarStyle{
// Add If/else conditions based on which style required on which condition
return UIStatusBarStyleLightContent;
}
Call this code when you want to change the status bar style..
[self preferredStatusBarStyle];
[self setNeedsStatusBarAppearanceUpdate];
In my project(written programmatically) in some files I hide the Navigation Bar, in other files I change the Navigation Bar color. Yes, I can do this just writing code at every single file where I want some specific Navigation Bar, but its so buggy and not the right way.
I tried to write a class, subclass of UINavigationController, where I loop through all my viewControllers and hide the Navigation Bar in specific files, but its not working.
Can anyone please help me to figure out it? What is the right way to control all the Navigation Bars changes(actions) from one file?
Thank you in advance.
What you want to do is subclass the UINavigationViewController and override the pushViewController method. Your ViewControllers should conform to a protocol and you should check inside the pushViewController if the ViewController conforms to that protocol and if so check if it implemented the methods from the protocol and based on that layout your UI.
Example:
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
if ([controller conformsToProtocol:#protocol(MyProtocol)]) {
id<MyProtocol> protocolVC = (id)controller;
if([protocolVC barColor]){
UIColor *color = [protocolVC barColor];
//Set the bar color
}
}
[super pushViewController:viewController animated:animated];
}
I am trying to change the status bar style of one of my viewcontrollers. I have put this
set the view based status bar to YES in the plist
2.
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
Added this also
[self setNeedsStatusBarAppearanceUpdate]
It works i.e I can see the font color white but just after some time it changes back to its previous type..
If you are experiencing status bar changing color itself during runtime
try setting set the UIViewControllerBasedStatusBarAppearance to NO in the plist.
And inside your viewController.. set the appearance call inside
-(void)viewDidLayoutSubviews
{
if ([self respondsToSelector:#selector(setNeedsStatusBarAppearanceUpdate)]) {
[self setNeedsStatusBarAppearanceUpdate];
}
}
write following code
-(void)viewWillAppear:(BOOL)Animated{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
This is the only thing I could get working for iOS7
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
You can check this code, a little trick – but useful sometimes.
I have a UIViewController with a childViewController.
The childViewController either takes up the entire screen or parts of the screens, overlaying on top of the parentViewController.
When it takes up the entire screen I would like to change the UIStatusBarStyle.
In my plist, I have added View controller-based status bar appearance and set it to NO.
In the childViewController I have the following:
-(UIStatusBarStyle)preferredStatusBarStyle {
if (self.isFullScreen) {
return UIStatusBarStyleDefault;
} else {
return UIStatusBarStyleLightContent;
}
}
-(UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
return UIStatusBarAnimationFade;
}
When making the transition from half and fullscreen I call:
[self setNeedsStatusBarAppearanceUpdate];
But my UIStatusBar does not change appearance from light to dark.
A regular call to:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
works fine, however but I would like to take advantage of the fact that I can match the animation duration for the change inside an animation block.
Thank you.
You should set the UIViewControllerBasedStatusBarAppearance to YES in the plist for using -(UIStatusBarStyle)preferredStatusBarStyle method.
The iOS 7 Transition Guide give a good hint how to change the UIStatusBarStyle dynamically in a UIViewController using
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleDefault;
}
together with [self setNeedsStatusBarAppearanceUpdate];
This works fine in a single view application. However, I'm now trying to change the UIStatusBarStyle in a modal view to UIStatusBarStyleLightContent. There is a MainViewController which segues to the ModalViewController, which itself is embedded in a NavigationController. The ModalViewController has set its delegate to the MainViewController.
I tried to call [self setNeedsStatusBarAppearanceUpdate]; in the ModalViewController together with the following method in that class without effect:
// In ModalViewController.m
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
I also tried to call [self setNeedsStatusBarAppearanceUpdate]; in MainViewController on prepareForSegue: sender: method with conditions in - (UIStatusBarStyle)preferredStatusBarStyle {} to return UIStatusBarStyleLightContent when the modal view is presented - but that has no effects, too.
How can I change the UIStatusBarStyle in the modal view?
EDIT: Post updated: I need to mention that the ModalViewController is embedded in a NavigationController with a NavigationBar. With NavigationBar set to hidden to above call of [self setNeedsStatusBarAppearanceUpdate]; in ModalViewController works fine. But not when the Bar is visible.
You need a ViewController that's showing in Fullscreen to return the appropriate status bar infos. In your case: The NavigationController which contains ModalViewController needs to implement preferredStatusBarStyle and return UIStatusBarStyleLightContent.
A call to setNeedsStatusBarAppearanceUpdate is only necessary if the values a view controller returns actually change. When the view controller is first presented they are queried anyway.
We should notice that non-fullscreen modalVC CAN use modalPresentationCapturesStatusBarAppearance to control the statusBar style.
Anyone who wanna know more about Status Bar control should not ignore the UIViewController Managing the Status Bar.
Update at 2015-11-06:
And make sure you have set UIViewControllerBasedStatusBarAppearance described in iOS Keys
Update at 2018.04.09:
I noticed that viewController in a navController may not get call prefersStatusBarHidden with iOS 10.0 - 10.2. Custom your navigationController to ensure that
#implementation YourCustomNavController
//for iOS 10.0 - iOS 10.2
- (BOOL)prefersStatusBarHidden {
UIViewController *childVC = [self childViewControllerForStatusBarHidden];
if (childVC) {
return [childVC prefersStatusBarHidden];
}
return [super prefersStatusBarHidden];
}
#end
And anyone who want to go deeper inside can dig into UIKit +[UIViewController _currentStatusBarStyleViewController] using Hopper or IDA Pro. It may helps you solve these kinds of bugs.
The key to making this work is that only the fullscreen view controller get's to dictate the style of the status bar.
If you are using a navigation controller and want to control the status bar on a per view controller basis, you'll want to subclass UINavigationController and implement preferredStatusBarStyle such that it returns the topViewController's preference.
Make sure you change the class reference in your storyboard scene fromUINavigationController to your subclass (e.g. MyNavigationController in the example below).
(The following works for me. If your app is TabBar based, you'll want to do something similar by subclassing the UITabBarController but I haven't tried that out).
#interface MyNavigationController : UINavigationController
#end
#implementation MyNavigationController
- (UIStatusBarStyle)preferredStatusBarStyle
{
return self.topViewController.preferredStatusBarStyle;
}
#end
To change the status bar of the UINavigationController embedding your ViewController without subclassing UINavigationController, use this:
navigationController?.navigationBar.barStyle = .Black // to make the status bar text white
.Black will make the text white (status bar and the view's title), while .Default has a black title and status bar.
I had a side menu/reveal controller (SWRevealController) which turns out to always be the root controller for status bar queries. Overriding childViewControllerForStatusBarStyle let me re-route the query to the front most controller.
/**
This view is always considered the topmost for status bar color queries.
Pass the query along to what we're showing in front.
*/
- (UIViewController *)childViewControllerForStatusBarStyle
{
UIViewController *front = self.frontViewController;
if ([front isKindOfClass:[UINavigationController class]])
return ((UINavigationController*)front).topViewController;
else
return front;
}
It seems like the app goes off the statusBarStyle of the topmost viewController. So if you add another viewController on top of your current one, it now gets its cues from the new viewController.
This works for me:
Set View controller-based status bar appearance to NO
Set Status bar style to UIStatusBarStyleLightContent (just copy that value)
In appDelegate use [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
Hope it helps (ref: ios7 status bar changing back to black on modal views?)
Just look up if your app's rootViewController need to override -(UIStatusBarStyle)preferredStatusBarStyle method
All of the above work. However sometimes I find it really a pain in the bottom to go and change every instance in the Storyboard etc... So here's something that works for me that also involves subclassing.
First create the subclass:
#interface HHNavLightColorBarController : UINavigationController
#end
#implementation HHNavLightColorBarController
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
#end
Then using the magic of Objective-C and a little bit of the <objc/runtime.h>
When you have a reference of the view controller and your presenting it:
UINavigationController *navVC = ...; // Init in your usual way
object_setClass(navVC, [HHNavLightColorBarController class]);
[self presentViewController:nav animated:YES completion:^{
NSLog(#"Launch Modal View Controller");
}];
Sometimes it seems a bit less intrusive. You could probably even create a category that checks to see if your kindOfClass is a navigation controller and auto do it for you. Anyways, the answer is above by jaetzold, I just found this to be handy.