I have a tabBarApp,
the 1 tab is a NavigationController and include the status bar
the 2 is a simple viewCOntroller where I added a NavigationBar ( it include the status bar)
the 3 tab doesn't have a status bar
I changed my Plist file to viewControllerBasedStatusBarAppearence to YES because I need each tab to have a different handling with the status bar ( the 1st and 2nd tab must have it, but the 3rd must have it hidden )
I wrote this inside the first two controllers...
override funct preferredStatusBarStyle() -> UIStatusBarStyle { return UIStatusBarStyle.LightContent }
override func prefersStatusBarHidden() -> Bool { return false }
and I wrote this inside the third controller
override func prefersStatusBarHidden() -> Bool { return true }
but it doesn't work. the 3rd controller doesn't have the status bar as I am expecting.
the 1st controller have the status bar of the same color of my nav bar
but the 2nd controller doesn't get the nav bar color ( probably cause its not a nav controller, but just a navBar )
so how can I set the bar to have the color I want without getting it from the NavBarController?
and how can I set the items in the status bar ( the icons... ) to have white color instead of black? ( the navbar text are white )
If you want to change the color of the content in the status bar (without using the UIViewController/UINavigation Controller automatic stuff) (so your 2 view controller) you can use the setStatusBarStyle(_ statusBarStyle: UIStatusBarStyle, animated animated: Bool) on UIApplication. So place the following in viewWillAppear (or wherever it makes sense/works best) in your 2 view controller:
UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: false)
Docs:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/#//apple_ref/occ/instm/UIApplication/setStatusBarStyle:animated:
setStatusBarStyle
Is now deprecated in iOS 9 and the current way of changing status bar style is:
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.Default
}
Changing .Default to .LightContent for light
Related
I'm trying to change the status bar text to white on some of the view controllers, but on a few others it still needs to be black. (so cannot change it globally for the whole app).
Everything works fine, except the first few seconds, when clicking on different tab bars, when there is a glitch, and half of the status bar text becomes black, instead of white. Then everything updates perfectly.
The structure is like this:
A tab bar controller with a few tabs, each tab containing a navigation controller, containing a view controller.
Having navigation controllers made it necessary to change the navigationController?.navigationBar.barStyle = .black to make it work.
After pressing a few times on tabs, it works fine.
First thing I did of course was to set to YES the View controller-based status bar appearance from the .plist
I also have override the preferredStatusBarStyle, using a boolean to set which view controllers should have the white or black status bar text:
override var preferredStatusBarStyle: UIStatusBarStyle {
return coloredNavigationBar ? .lightContent : .default
}
var coloredNavigationBar: Bool = true
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if coloredNavigationBar {
navigationController?.navigationBar.barStyle = .black
} else {
navigationController?.navigationBar.barStyle = .default
}
setNeedsStatusBarAppearanceUpdate()
}
The code pasted is from the base view controller used everywhere.
Yes! #matt was right, thank you. Indeed iOS gets confused when using a tabbar.
The solution was to add this to the TabBarController:
override public var childForStatusBarStyle: UIViewController? {
if let controller = selectedViewController as? UINavigationController {
return controller.visibleViewController
}
return selectedViewController
}
I am able to hide the status bar on the launch screen by setting Status bar is initially hidden to YES in Info.plist and then I want to show it on my first view controller with a .lightContent style.
However UIApplication.shared.statusBarStyle = .lightContent is deprecated since iOS 9 (so I don't want to use it) and using the following code give me a black status bar on my first view controller.
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
How can I change the status bar style when my first view controller load?
I am trying to find a global solution like UIApplication.shared.statusBarStyle = .lightContent since I don't really want to set the status bar style for every view controller.
I have tested the solutions with View controller-based status bar appearance set to YES and NO.
The problem you're experiencing is that UINavigationController doesn't defer the choice of status bar to its view controllers.
Instead, for a navigation controller, the status bar style can be set by adjusting the barStyle property of its navigationBar.
If it is set to a black style, then the status bar will be light style:
navigationController?.navigationBar.barStyle = .black
Note, that this will also change the color of the navigationBar, however you can still set the bar's colour to whatever you want using barTintColor:
navigationController?.navigationBar.barTintColor = .purple
If you want to make a global change, so that all instances of UINavigationController use the same status bar style (useful if you've got multiple tabs all of which use a navigation controller), then you can add an extension on UINavigationController and override the preferredStatusBarStyle property:
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
A final option, is to defer the choice to the view controllers in the navigation controller's stack.
To do that, override the childViewControllerForStatusBarStyle property of your navigation controller extension and have it return the topViewController:
extension UINavigationController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return topViewController
}
}
In this case, you'll need to override preferredStatusBarStyle in all of your view controllers (not the optimal approach, but it's an option if you need this granular level of control on a per-child-controller basis).
All of these solutions require that your View controller-based status bar appearance key in Info.plist is set to YES.
I want white status bar in my app. For this I set View controller-based status bar appearance to NO and Status bar style to UIStatusBarStyleLightContent. But now I need to hide status bar in some view controllers. To hide it I have to set View controller-based status bar appearance to YES and add - (BOOL)prefersStatusBarHidden {return YES;}. But status bar is black now. It's black when View controller-based status bar appearance is YES and white if NO. So the question is, how to set white status bar and hide it?
UPD:
code in VC that I want to have white status bar (prefferdSTatusBarStyle not called)
code in VC with hidden status bar
.plist settings
Result is black status bar, that hides in some VC
UPD2:
I know it's bad to use deprecated methods but with [[UIApplication sharedApplication] setStatusBarHidden:YES]; everything works as I want. If anyone have better solution please let me know.
This is the swift version:
To hide the status bar or change it's appearance, you need to override the following properties in your view controller itself
override var prefersStatusBarHidden: Bool{
return true
}
the above hides the status bar and below if you want to set it to white:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
In your plist file add View controller-based status bar appearance Bool property and set it to YES.
Now in your view controller add the methods like below:
// TO MAKE STATUS BAR WHITE
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
// TO MAKE STATUS BAR BLACK
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
// RETURN TRUE TO HIDE AND FALSE TO SHOW STATUS BAR
override func prefersStatusBarHidden() -> Bool {
return true
}
For Objective-C
- (BOOL)prefersStatusBarHidden {
return NO;
}
-(UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
For removing redundant code you can make a BaseViewController as subclass of UIViewController and add the methods in that class. And override the method in the class which requires change.
you can set using xcode status bar style is "light"
if your viewcontroller is embedded in UInavigationController then try writing this code in your
-(BOOL)prefreStatusBarHidden
{
return [self.navigationController prefersStatusBarHidden];
}
You can do this by setting the navigation background image in your base viewcontroller.
UIImage *bgImage = [UIImage imageNamed:#"bg_navigationbar"];
[self.navigationController.navigationBar setBackgroundImage:bgImage forBarMetrics:UIBarMetricsDefault];
I need a white status bar for my main initial ViewController, but also be able to hide it in another ViewController. I can do one or the other, but not both at the same time. Any suggestions?
I set it to white by setting
View controller-based status bar appearance key to NO in the
Info.plist
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
And to hide it (on another ViewController presented modally) I do,
override func prefersStatusBarHidden() -> Bool {
return statusBarHidden
}
however it won't hide unless I remove the key I previously added to the Info.plist, but if I remove the key, then the status bar goes back to black.
EDIT-MY Solution:
The View controller classes were not working in my case because I have the main view controller embedded in a navigation controller, my fix was to override the same methods but for the navigation controller instead of the view controller in question.
extension UINavigationController {
public override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
}
If you add
View controller-based status bar appearance key to NO in the Info.plist
You should use [UIApplication setStatusBarHidden:withAnimation:] and [UIApplication setStatusBarStyle:animated:] to change to the statusbar's appearance. Your method won't be called
As it is said in apple's document:
UIViewControllerBasedStatusBarAppearance (Boolean - iOS) Specifies whether the status bar appearance is based on the style preferred by the view controller that is currently under the status bar. When this key is not present or its value is set to YES, the view controller determines the status bar style. When the key is set to NO, view controllers (or the app) must each set the status bar style explicitly using the UIApplication object.
UIViewControllerBasedStatusBarAppearance key is the same as View controller-based status bar appearance key.
If you don't add the key,your method should work. try add both methods in these two Viewcontrollers, and add some breakpoint to see they're called or override by mistake.
The code in Swift 3.0 Xcode 8.2 works for me:
override open var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override open var prefersStatusBarHidden: Bool {
return true
}
When I run my application, you can see the navigation bar animates in very quickly, it seems like I only catch the end. The animation also seems like it slides down from the top. I have written no code for it to do this! That's why it's weird!
Here's the weirder thing. In the info.plist if I set "View controller-based status bar appearance" to "NO" this does NOT happen. It only happens when I set it to "YES"!
I want "View controller-based status bar appearance" to be set to "YES" because I want to be able to turn it off on specific view controllers using:
override func prefersStatusBarHidden() -> Bool {
return true
}
Please help!
Pay attention to View controller-based status bar appearance in plist file, it means, that you will determine logic of status bar inside your app.
Do you assume that UIStatusBar and UINavigationBar are the same?
Definetly not.
So you function:
override func prefersStatusBarHidden() -> Bool {
return true
}
is hiding status bar (20px bar with battery, clocks and mobile cell).
If you want to change it's animation you should use:
override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
return .None
}
If you want to hide UINavigationBar in some view controller, you should call inside view controller:
navigationController?.setNavigationBarHidden(true, animated: false)