the status bar style for my application is white except when image picker controller is presented and I have already extend my UINavigationController but it doesn't seem to be working on any view present only on pushed views does anyone have solution??
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .lightContent
}
}
I have also try this method , but the navigationController is a let and the
preferredStatusBarStyle is read-only
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
viewController.navigationItem.title = "willShow"
navigationController.preferredStatusBarStyle = UIStatusBarStyle.lightContent
}
When you present something modally and you want it to determine the status bar style you need to set modalPresentationCapturesStatusBarAppearance = true
For example:
let navigationController = UINavigationController(rootViewController: MyViewController())
navigationController.modalPresentationCapturesStatusBarAppearance = true
present(navigationController, animated: true)
You'll also need to check if the current UINavigationController is a UIImagePickerController and return .lightContent from preferredStatusBarStyle as UIImagePickerController has a prefers the .default out of the box.
open override var preferredStatusBarStyle: UIStatusBarStyle {
if self is UIImagePickerController {
return .lightContent
}
return topViewController?.preferredStatusBarStyle ?? .lightContent
}
I created a new project. I have a NavigationController. In the RootViewController I have a containerView with a table and just one cell. If I click on the cell I push a new UIViewController. So my Main.storyboard looks like this:
What I want:
I want first to have a white NavigationBartitle. Then pushing to secondVC I want to change the NavigationBarTitle to black. Then clicking on back the color should change back to a white title.
What I've did:
I did a custom NavigationViewController. There I was changing the func willShow viewController. In this I wrote the titleColor should change depending on which screen the navigationController changes to.
My code:
import UIKit
class SettingsNavigationViewController: UINavigationController {}
// MARK: - Controller Lifecycle
extension SettingsNavigationViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
override var preferredStatusBarStyle: UIStatusBarStyle {
guard let child = self.childViewControllers.last else {
return .lightContent
}
return child is ViewController ? .lightContent : .default
}
}
// MARK: - NavigationController Delegate Implementation
extension SettingsNavigationViewController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
let isSettingsContainer = viewController is ViewController
let backgroundColor = isSettingsContainer ? UIColor.cyan : UIColor.white
let titleColor = isSettingsContainer ? UIColor.white : UIColor.black
let image = isSettingsContainer ? UIImage() : nil
navigationController.navigationBar.shadowImage = image
navigationController.navigationBar.setBackgroundImage(image, for: .default)
navigationController.transitionCoordinator?.animate(alongsideTransition: { (context) in
navigationController.navigationBar.tintColor = titleColor
navigationController.navigationBar.barTintColor = backgroundColor
navigationController.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor : titleColor]
})
}
}
What happened instead:
If I change the screen to seconndVC the navBarTitleColor changes black. If I click on back it stays black. But it should change to white.
The complete project I also uploaded to github: https://github.com/Sonius94/stackNaviTitle
The possible solution could be, add a SecondViewController and in your SecondViewController you should implement the following :
override func willMove(toParentViewController parent: UIViewController?) {
super.willMove(toParentViewController: parent)
if parent == nil {
// Add your navigation bar appearance for FirstViewController
}
}
On a view controller, i want to set the color of status bar black but I am not able to change it. I am using below code for this purpose.
func setUpUI() {
self.navigationController?.setNavigationBarHidden(true, animated: false)
UIApplication.shared.statusBarStyle = UIStatusBarStyle.default
}
I have also added the value in info.plist
You just override the return value of the status bar, like this:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
Use below code for swift 4 and Xcode 9.2.
1) In
info.plist Set
View controller-based status bar appearance Key to
NO
2) In
AppDelegate
didFinishLaunchingWithOptions
set Below Code
let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
statusBar.backgroundColor = UIColor.red
}
UIApplication.shared.statusBarStyle = .lightContent
My app uses a dark navigation bar color. Therefore I set the status bar color to white (so it has a nice contrast).
I did this by setting the barStyle to black (to make the status bar white) and also setting the barTint to my dark red color. Works perfectly.
I present a SafariViewController like this:
func openWebsite(urlString: String) {
if let url = NSURL(string: urlString) {
let svc = SFSafariViewController(URL: url)
svc.delegate = self
self.presentViewController(svc, animated: true, completion: nil)
}
}
However the status bar of the presented SafariViewController still is white. This is a problem because the SVC navigation bar has the default white transparent iOS default style. So the status bar is basically invisible.
How can I fix that?
You can achieve that by wrapping SFSafariViewController with subclassed UINavigationController.
BlackStatusBarNavigationController.h
#interface BlackStatusBarNavigationController : UINavigationController
#end
BlackStatusBarNavigationController.h
#interface BlackStatusBarNavigationController ()
#end
#implementation BlackStatusBarNavigationController
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleDefault;
}
#end
Use like this:
UINavigationController *navigationController = [[BlackStatusBarNavigationController alloc] initWithRootViewController:viewController];
navigationController.navigationBarHidden = YES;
[self presentViewController:navigationController animated:YES completion:nil];
There are 2 ways you can override preferredStatusBarStyle in your viewControllers and return the one you want
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .Default
}
or you can set it manually with
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: UIStatusBarAnimation.None)
how ever for setting it through sharedApplicaion you will need to add this in to your plist
"View controller-based status bar appearance" to NO
If you want to set background color of status bar for iOS 13+, you can try to set it force like this.
import UIKit
import SafariServices
class CustomSFSafariViewController: SFSafariViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
if #available(iOS 13.0, *) {
UIApplication.shared.statusBarView?.backgroundColor = .purple
}
setNeedsStatusBarAppearanceUpdate()
}
}
extension UIApplication {
#available(iOS 13.0, *)
var statusBarView: UIView? {
let tag = 3848245
let keyWindow = connectedScenes
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows.first
if let statusBar = keyWindow?.viewWithTag(tag) {
return statusBar
} else {
let height = keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?? .zero
let statusBarView = UIView(frame: height)
statusBarView.tag = tag
statusBarView.layer.zPosition = 999999
keyWindow?.addSubview(statusBarView)
return statusBarView
}
}
}
There are few useful properties for customization of SFSafariViewController which you can use:
preferredControlTintColor (color of toolbar items)
preferredBarTintColor (color of toolbar)
P.S. don't forget to use CustomSFSafariViewController instead of SFSafariViewController. You can do it like this.
let safariViewController = CustomSFSafariViewController(url: url)
UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: true)
I use this one to change status bar to light in all app. But now I need to change it in just one View Controller back to black. How can I do that?
Set View controller-based status bar appearance in your project.plist to NO
Use viewWillAppear and will viewWillDisappear to set and reset the statusBarStyle, while keeping a property with the previous statusBarStyle like this
let initialStatusBarStyle : UIStatusBarStyle
func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
initialStatusBarStyle = UIApplication.sharedApplication().statusBarStyle
UIApplication.sharedApplication().setStatusBarStyle(.LightContent, animated: animated)
}
func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
UIApplication.sharedApplication().setStatusBarStyle(initialStatusBarStyle, animated: animated)
}
Xcode 8.1, Swift 3 Solution with #IBDesignable
This solution is a little bit different:
Subclass of UIViewController to centralize logic
No code for viewDidLoad or viewDidDisappear
Uses #IBDesignable so you can set your status bar color in the Attributes Inspector on the Storyboard
Step 1 - Setup Info.plist File
Step 2 - Subclass UIViewController
import UIKit
#IBDesignable
class DesignableViewController: UIViewController {
#IBInspectable var LightStatusBar: Bool = false
override var preferredStatusBarStyle: UIStatusBarStyle {
get {
if LightStatusBar {
return UIStatusBarStyle.lightContent
} else {
return UIStatusBarStyle.default
}
}
}
}
Step 3 - Inherit from DesignableViewController
Change the code for your ViewController(s) from:
class ViewController: UIViewController {
To:
class ViewController: DesignableViewController {
Step 4 - Set your preference on the Storyboard
Select the ViewControllers on the Storyboard and go to the Attributes Inspector:
Step 5 - Run project and test
In my project I setup a Tab Bar Controller with 2 View Controllers and switch back and forth between the two. Seems to work OK for me.
Solved:
Swift 3.1
Just using this code in View Controller:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
Swift 3
Set View controller-based status bar appearance in your project.plist to NO
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
UIApplication.shared.setStatusBarStyle(.default, animated: animated)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UIApplication.shared.setStatusBarStyle(.lightContent, animated: animated)
}
An Objective-C answer:
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
}
let color = UIColor(red:0.00, green:0.60, blue:0.48,alpha:1.0)
UINavigationBar.appearance().tintColor = UIColor.blue
UINavigationBar.appearance().barTintColor = color
OR
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
In swit4 this working fine in my project based on navigation bar
let app = UIApplication.shared
let statusBarHeight: CGFloat = app.statusBarFrame.size.height
let statusbarView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: statusBarHeight))
statusbarView.backgroundColor = UIColor.red
view.addSubview(statusbarView)
You can set status bar color using below code and its working for me
self.navigationController?.SetStatusBar(StatusBarbackgroundColor: ThemeBackColor, StatusTextColor: .black)
Thanks
Happy Coding :)
Swift 5,iOS 14,UIKit
Step 1: Add Status bar style
Step 2: Change in Info.Plist
Add View controller-based status bar appearance key with NO value
Step 3: In your base view controller add this extension
extension UIViewController
{
func setStatusBarColor(){
if #available(iOS 13, *)
{
let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
let statusBarFrame = window?.windowScene?.statusBarManager?.statusBarFrame
let statusBar = UIView(frame: (statusBarFrame)!)
statusBar.backgroundColor = .orange
window?.addSubview(statusBar)
} else {
// ADD THE STATUS BAR AND SET A CUSTOM COLOR
let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
statusBar.backgroundColor = .orange
}
UIApplication.shared.statusBarStyle = .lightContent
}
}
}
Step 4: In your view controller use this extension
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setStatusBarColor()
}
If you have derived your view controllers from a common view controller then, you can simply do it like this:
Step 1:
Add this key to your app's info.plist file.
Step 2:
override this in common view controller (or a ParentViewController).
override var preferredStatusBarStyle: UIStatusBarStyle {
if self is YourChildViewController {
return .lightContent
}
return .default
}
That's it! No more fancy things.