How to change statusBarStyle programmatically? - ios

I am building an app for iOS13. I want to change the text color of status bar according to the color scheme which user can select. It seems the text color of status bar cannot be changed directly, so I try to change the statusBarStyle instead.
First I try:
var myStatusBarStyle = UIStatusBarStyle.default { didSet { setNeedsStatusBarAppearanceUpdate() } }
override var preferredStatusBarStyle : UIStatusBarStyle { return myStatusBarStyle; }
But it did not work.
Then I try:
UIApplication.shared.statusBarStyle = myStatusBarStyle;
It does do the job! But Xcode gives a warnning: " 'statusBarStyle' was deprecated in iOS 13.0: Use the statusBarManager property of the window scene insted."
so, in sceneWillEnterForeground(_ scene: UIScene) I try:
guard let ws = (scene as? UIWindowScene) else { return }
if let t = ws.statusBarManager { print(t.statusBarStyle) }
Unfortunately, t.statusBarStyle is readonly.
Now, how can I do?
ps: I have no Navigation Bar or Tab Bar in the Main.storyboard.

in iOS 13, we are not allowed to do that but there are always escape roots..
I used
self.navigationController?.navigationBar.barStyle = .black
To make status bar black and it works
You can use various options instead of black as you like (.default , .blackTranslucent , .blackOpaque) in place of .black

Related

How can I change color of Status Bar background? [duplicate]

This question already has an answer here:
How to set color of status bar showing carrier, time, and battery on top
(1 answer)
Closed 3 years ago.
When I scroll down Status bar across my text, and its seems terribly
Can I make a status bar background grey or dark and text of status bar light?
The style of the status bar can be changed to a status bar with white content. Go to the ViewController.swift file and add the following lines of code.
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
enum UIStatusBarStyle : Int
case default : A dark status bar, intended for use on light
backgrounds.
case lightContent : A light status bar, intended for use on dark
backgrounds.
case darkContent : A dark status bar, intended for use on light
backgrounds.
If you want to change the background color of the status bar together, you can do the following:
if #available(iOS 13.0, *) {
let statusBarView = UIView(frame: view.window?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero)
statusBarView.backgroundColor = backgroundColor
view.addSubview(statusBarView)
} else {
// Fallback on earlier versions
let statusBarView = UIView(frame: UIApplication.shared.statusBarFrame)
statusBarView.backgroundColor = backgroundColor
view.addSubview(statusBarView)
}
add in your appDelegate this code
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UINavigationBar.appearance().barStyle = .blackOpaque
return true
}
or in your info plist use
or in specific view
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
navigationController?.navigationBar.barStyle = .blackOpaque
}
for view controller
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}

Dynamically Change iOS Nav Bar Color (Dark Mode)

I'm trying to implement a toggle for dark mode in my app - this would involve toggling the nav bar color to black when the UIViewController is already visible on the screen. I'm aware of how to do this by setting
UINavigationBar.appearance().barTintColor = .black
UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
UINavigationBar.appearance().isTranslucent = false
in the AppDelegate, however, this won't work in this case as it needs to be done dynamically.
I've also tried navigationController?.navigationBar.barTintColor = UIColor.white but this doesn't work either.
UPDATE:
I think a lot of the responses were confused with the purpose of this question - this is NOT at all related to the iOS13 Dark Mode which was just released - it is an INDEPENDENT dark mode feature I want to add to my app (similar to other apps like Messenger etc which had dark mode available IN-APP before iOS 13 was released). What I need to do is dynamically update the color of the UINavigationBar AFTER it has been already displayed on the screen, the same way I can change the background color of a view by doing view.backgroundColor = .white and this will update the color in real-time on screen.
Achieved this by making the nav bar translucent (in AppDelegate):
let barAppearance = UINavigationBar.appearance()
barAppearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: appRed]
barAppearance.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
barAppearance.shadowImage = UIImage()
barAppearance.isTranslucent = true
Next I create a view and place it behind the nav bar as follows (using SnapKit):
let coverView = UIView()
cover.snp.makeConstraints {
make in
make.left.right.top.equalTo(self)
make.bottom.equalTo(self.snp.top).offset(universalNumber(num: parent!.topbarHeight))
}
where the parent is my UIViewController and topBarHeight is:
extension UIViewController {
/**
* Height of status bar + navigation bar (if navigation bar exist)
*/
var topbarHeight: CGFloat {
return UIApplication.shared.statusBarFrame.size.height +
(self.navigationController?.navigationBar.frame.height ?? 0.0)
}
}
Finally, to update the color I set
coverView.backgroundColor = universalWhite()
where
func universalWhite() -> UIColor {
let defaults = UserDefaults.standard
let darkMode = defaults.bool(forKey: "darkMode")
if darkMode {
return .black
} else {
return .white
}
}
You may want to check out the traits provided with the UIViewController to determine the current Interface style, instead of a manual check for versions running iOS 13+. Using this method, you can define colors in your Assets folder for both appearances.
For below iOS 13, you can use something similar to what #byaruah stated, but that is not a global effect. You should also consider using the UINavigationBar.appearance() functionality for a global approach.

How to set statusBarStyle inside AppDelegate with no warnings

Before I start I would to apologise if this question is duplicated as I seen plenty of question but I can't find out what I need.
I want to create a global Status, navigation, toolbar bar style and, if possible, the bottom part of the view on iPhones X onwards from my app delegate only so I don't have to set it form each Viewcontroller.
So far I have:
extension UIApplication {
var statusBarView: UIView? {
return value(forKey: "statusBar") as? UIView
}
}
and a function called inside the didFinishLaunchingWithOptions method
private func setupNavigationBarStyle(){
UIApplication.shared.statusBarView!.backgroundColor = UIColor.AppColors.statusBar
UIApplication.shared.statusBarStyle = .lightContent
UINavigationBar.appearance().barTintColor = .brown
UINavigationBar.appearance().tintColor = .green
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.yellow]
UINavigationBar.appearance().isTranslucent = false
}
I attach a dummy design for my view controller using the storyboard
and the final result is
Despite not being the best design I have 3 questions.
UIApplication.shared.statusBarStyle = .lightContent is deprecated and it shows a warning and I don't want that.
How can I change the color for the bottom for iPhone X onwards (currently in red and and where the Horizontal line is).
Can I change statusBarStyle for another not defined and change the text color in my status bar Purple?
I hope it will help you
UIApplication.shared.statusBarStyle = .lightContent is deprecated and it shows a warning and I don't want that.
Go to Project -> Target, Set Status Bar Style to Light
How can I change the color for the bottom for iPhone X onwards (currently in red and and where the Horizontal line is).
it is not possible to modify the color, and you shouldn’t worry about it, since it’s out of your control and guaranteed to be visible.For Info(https://medium.freecodecamp.org/reverse-engineering-the-iphone-x-home-indicator-color-a4c112f84d34).
Can I change statusBarStyle for another not defined and change the text color in my status bar Purple?
func setStatusBarBackgroundColor(color: UIColor) {
guard let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView else { return }
statusBar.backgroundColor = color
}
//Use self.setStatusBarBackgroundColor(color: .purple)
Thanks

How to change UIDocumentInteractionController Done button text and background color

How to change the background color and text color of done button? Is there a way that I can change the navigationbar color and navigation bar title color and bottom bar color also? Attached screenshot for reference:
I solved it. Here is the code working for me perfectly:
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
UINavigationBar.appearance().barTintColor = Colors.redColor()
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName : UIColor.white, NSFontAttributeName: UIFont.systemFont(ofSize: 14, weight: UIFontWeightBold)]
return self
}
It's a little hacky as its relying on the fact that QLPreviewController is the class implementing the UIDocumentInteractionController but something like this is the least intrusive solution. Do it before you display the UIDocumentInteractionController
import QuickLook
UIBarButtonItem.appearance(whenContainedInInstancesOf [QLPreviewController.self]).tintColor = UIColor.black
I have a idear to change the bar color:
let allNavigationBar = UINavigationBar.appearance()
allNavigationBar.barTintColor = UIColor.red // change the bar background color
allNavigationBar.tintColor = UIColor.black // change the Done button's tintColor
let alloolbar = UIToolbar.appearance()
allToolbar.barTintColor = UIColor.red // dones't work, try backgroundImage
allToolbar.backgroundColor = UIColor.blue // dones't work
allToolbar.tintColor = UIColor.brown // change the toolbar's item tint color
but this method has a great effect,all your UINavigationBarand UIToolBar will make that change.
Hope anyone else can give a better solusion.
You can change the tint color of the window temporally.
func presentDocument() {
//present the controller here
self.appDelegate.window.tintColor = UIColor.red
}
Then change it back later:
func documentInteractionControllerDidEndPreview(documentInteractionController) { //replace parameter with your uidocumentviewinteractioncontroller
self.appDelegate.window.tintColor = UIColor.white
}
#Dee. I guess you have asked this part in one of your other question. In that case you were not able to show that preview controller. In that question suggested answer is to return "self" from that delegate method. If you implement that correctly then your preview will use same navigation bar colour as its parent controller is using. I mean if you have opened UIDocumentInteractionController directly from some ViewController then UIDocumentInteractionController will use its parent viewController's navigation bar colour. This may help you to change Done button colour
Try this : (You need to implement UIDocumentInteractionControllerDelegate)
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self.navigationController ?? self
}
let QLNavAppearance = UINavigationBar.appearance(whenContainedInInstancesOf: [QLPreviewController.self])
QLNavAppearance.tintColor = UIColor.red // some
QLNavAppearance.barTintColor = UIColor.red // some
QLNavAppearance.backgroundColor = UIColor.red // some

UINavigationBar tint color does not update

I am implementing a dark mode in my app. Here is my code (that I call when the screen is double tapped):
if darkMode == false {
UINavigationBar.appearance().tintColor = UIColor(hexString: "#3A3A3A")
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName:UIColor.whiteColor()]
UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent
} else {
UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.Default
UINavigationBar.appearance().barTintColor = UIColor(hexString: "#FFFDF3")
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName:UIColor.blackColor()]
The only thing that updates is my status bar, but the navigation bar does update after I go into another view and return back to the main view. Why is that? Is there something I'm doing wrong?
I was just dealing with the same issue, turns out if you change appearance() proxy at runtime it doesn't have any effect. You need to change directly the properties of instances. So what you need to do is have subclassed UINavigationBarController with method where you set the colors and status bar appearance, for instance:
class ColorNavigationController: UINavigationController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
setupForColor(UIFactory.sharedInstance.tintColor) //provides default color
}
func setupForColor(color: UIColor) {
navigationBar.tintColor = color
navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.whiteColor()]
UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent
}
}
Then when you double tap the screen:
if let colorNavigationController = self.navigationController as? ColorNavigationController {
colorNavigationController.setupForColor(UIColor.redColor) // based on your current scheme
}
Got it. You can't change appearance() at runtime, but you can just do navigationController?.navigationBar.tintColor = UIColor.redColor()

Resources