4

I want to add a settings view in my app and I have been trying to update the color theme of the entire app in the settings preferences.

The navigation bar and color theme does not seem to change with the user selection

this is a gif demo of the app : link => demo app settings: theme color not updating

This is my AppDelegate: I have tried to trigger the change with a protocol/delegate. no luck ? I believe the issue is not related to the delegate. the delegate method is implemented correctly.

the issue comes from the navigationbar that needs to be redrawn after didFinishLaunching I believe. I came accross this question (Changing navigation bar color in Swift), but I have not been able to find the correct solution so far. This is very challenging

class AppDelegate: UIResponder, UIApplicationDelegate, SettingsDelegate {

var lightColor:UIColor?
var darkColor:UIColor?
var darkColorLighter:UIColor?
var colorThemes:[String : AnyObject] = [String : AnyObject]()
let redColor:UIColor = UIColor(red: 192.0/255.0, green: 57.0/255.0, blue: 43.0/255.0, alpha: 1.0)

var window: UIWindow?
var defaults = UserDefaults.standard
var colorSettingsDefaults = UserDefaults(suiteName: "group.com.Links")

var THEMECOLOR:UIColor?
var TEXTCOLOR:UIColor?
var BORDERADIUS:CGFloat?
var themeSelected:Theme?
let setThemeAppearance:NSNotification.Name = NSNotification.Name("themeAppearance")

func getColorSettingsDefaults(completion:(_ theme:Theme)->()) {

    if let _ = colorSettingsDefaults?.value(forKey: "ThemeAppearance") as? String {
        //if color settings default avalaible
        themeSelected = getTheme()
        print("defaults available")

    } else {
        //if NO color settings default avalaible - default is DARK THEME
        themeSelected = .dark
        print("dark theme by default")
    }

    completion(themeSelected!)
}

func getTheme() -> Theme {
    return colorSettingsDefaults!.value(forKey: "ThemeAppearance") as! String == "light" ? .light : .dark
}


func applyTheme(themeSelected:Theme) {

    if themeSelected == . dark {
        THEMECOLOR = darkColor
        TEXTCOLOR = lightColor
    } else {
        THEMECOLOR = lightColor
        TEXTCOLOR = darkColor
    }

    //radius
    BORDERADIUS = 5.0
}


func setColorThemes() {
    //application theme colors
    darkColor = UIColor(red: 52.0/255.0, green: 73.0/255.0, blue: 94.0/255.0, alpha: 1.0)
    darkColorLighter = UIColor(red: 52.0/255.0, green: 73.0/255.0, blue: 94.0/255.0, alpha: 0.6)
    lightColor = UIColor.white
    colorThemes = ["light": lightColor!, "dark": darkColor!]
}

func changeAppearance(apptheme:Theme) {

    //change navigation bar title color
    UINavigationBar.appearance().barTintColor = THEMECOLOR
    UINavigationBar.appearance().tintColor = TEXTCOLOR


    window?.rootViewController?.navigationController?.navigationItem.rightBarButtonItem?.tintColor = TEXTCOLOR

    if apptheme == .dark {
        //change status bar to light for the dark theme
        UIApplication.shared.statusBarStyle = .lightContent
    } else {
        UIApplication.shared.statusBarStyle = .default
    }
}


func updateAppearance(appTheme:Theme) {

    UINavigationBar.appearance().barTintColor = UIColor.clear
    UINavigationBar.appearance().tintColor = UIColor.clear

    if appTheme == .dark {
        //change status bar to light for the dark theme
        UIApplication.shared.statusBarStyle = .lightContent
        UINavigationBar.appearance().backgroundColor = darkColor
        UINavigationBar.appearance().tintColor = lightColor

        window?.rootViewController?.navigationController?.navigationItem.rightBarButtonItem?.tintColor = lightColor

        UINavigationBar.appearance().barStyle = .default

    } else {
        UIApplication.shared.statusBarStyle = .default
        UINavigationBar.appearance().backgroundColor = lightColor
        UINavigationBar.appearance().tintColor = darkColor
        window?.rootViewController?.navigationController?.navigationItem.rightBarButtonItem?.tintColor = darkColor

         UINavigationBar.appearance().barStyle = .black
    }
}
Community
  • 1
  • 1
  • The `appearance` proxy only affects views created after an `appearance()` property is set. – rmaddy Apr 25 '17 at 16:02
  • I am using appearance in my code sample. is there another way to use the appearance() property once the app is already active? thanks for pointing me to the right direction. –  Apr 25 '17 at 17:35
  • Using `appearance` is fine for all new views. But any existing views have to be updated directly. – rmaddy Apr 25 '17 at 17:36
  • This is actually my question. I am on an existing view during the switch to another color theme. Is there a workaround to update the color (like a refresh). I have tried setLayoutIfNeeded() and setDisplayIfNeeded. did not work ? –  Apr 25 '17 at 22:29
  • You just need to perform the same changes on the current view that you doing on the `appearance` proxy but do it directly to the view. – rmaddy Apr 25 '17 at 23:20
  • oh I see. I will try that. thanks a lot! –  Apr 26 '17 at 02:11
  • That was super helpful. Thanks Again maddy –  Apr 26 '17 at 16:31

1 Answers1

3
  in viewDidLoad() or viewDidAppear()

  self.navigationController?.navigationBar.barTintColor = UIColor.black
  self.navigationController?.navigationBar.tintColor =  UIColor.white
  self.navigationController!.navigationBar.titleTextAttributes = 
  [NSForegroundColorAttributeName: UIColor.white]