Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 994
Alk Avatar asked Nov 06 '22 13:11

Alk


1 Answers

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
    }
 }
like image 83
Alk Avatar answered Nov 14 '22 23:11

Alk