Flo
Flo

Reputation: 89

change UITabBar.appearance().tintColor at runtime

I want to allow the user to change the whole App-Color. But whenever I select a color it is only changed after the App will be restarted.

Is there any option to change the color at runtime?

I've set up a Button with a function like this to create a ColorPicker

@IBAction func colorChange(_ sender: UIButton) {
        // Initializing Color Picker
        let picker = UIColorPickerViewController()

        // Setting the Initial Color of the Picker
        picker.selectedColor = UIColor(named: "MyGreen")!

        // Setting Delegate
        picker.delegate = self

        // Presenting the Color Picker
        self.present(picker, animated: true, completion: nil)
    }

And when the user picked a color, I make the changes in this function

func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
        defaults.set(viewController.selectedColor, forKey: "myColor")
        UITabBar.appearance().tintColor = viewController.selectedColor
    }

To change the color at startup I've implemented this in AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        var myColor = defaults.color(forKey: "myColor")
        if  myColor == nil {
            myColor = UIColor(named: "MyGreen")
        }
        UITabBar.appearance().tintColor = myColor
        
        return true
    }

Upvotes: 1

Views: 681

Answers (3)

Barry
Barry

Reputation: 1

If you just need to reload the tab bar after you assign the new UITabBarAppearance, you can assign a new UITabBarItem instance to your view controller, the new tab bar item will rendered using the updated UITabBarAppearance, there is no need to loop through whole subviews in your window.

let tab = UITabBarItem()
tab.image = UIImage(named: "image")
tab.selectedImage = UIImage(named: "selected_image")
self.tabBarItem = tab

Upvotes: 0

Flo
Flo

Reputation: 89

Someone gave me an Article to read how it can be done. https://zamzam.io/protocol-oriented-themes-for-ios-apps/

I've ended up doing it like this:

 func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
        defaults.set(viewController.selectedColor, forKey: "myColor")
        apply(for: UIApplication.shared, color: viewController.selectedColor)
    }

by adding this function

func apply(for application: UIApplication, color: UIColor) {
        UITabBar.appearance().tintColor = color
        application.windows.reload()
    }

and these extensions

public extension UIWindow {

    /// Unload all views and add back.
    /// Useful for applying `UIAppearance` changes to existing views.
    func reload() {
        subviews.forEach { view in
            view.removeFromSuperview()
            addSubview(view)
        }
    }
}

public extension Array where Element == UIWindow {
    
    /// Unload all views for each `UIWindow` and add back.
    /// Useful for applying `UIAppearance` changes to existing views.
    func reload() {
        forEach { $0.reload() }
    }
}

If it's good or not I don't know - but it worked for me.

Upvotes: 2

kennyzi yusuf
kennyzi yusuf

Reputation: 44

have you try using UITabBar.appearance().barTintColor ?

Upvotes: 0

Related Questions