I have three view controllers. In the first view controller (FirstVC), the navigation bar's bar tint color is clearColor and the bar itself is translucent. When I click on something, I push to SecondVC where the navigation bar needs to be opaque. So I set the barTintColor to some color value and set isTranslucent to false. When I push to ThirdVC from SecondVC, the navigation bar again needs to be translucent. The issue arises when I pop the ThirdVC and go back to SecondVC. The navigation bar appears as transparent for a second and then becomes opaque as required. I'm unable to understand the reason for the delay.
The following method is called from viewWillAppear()
of SecondVC. I have tried doing the same from the viewWillDisappear()
of ThirdVC, but to no effect.
fileprivate func configureNavigationBar(){
self.navigationController?.navigationBar.setBackgroundImage(nil, for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.barTintColor = Style.Movie.primaryBackgroundColor
let titleDict: NSDictionary = [NSForegroundColorAttributeName: UIColor.white]
self.navigationController?.navigationBar.titleTextAttributes = titleDict as? [String:Any]
}
It works fine if I swipe back instead of tapping on the back button.
use this function in thiredVC
override func willMove(toParentViewController parent: UIViewController?) {
self.navigationController?.navigationBar.barTintColor = color use in secondVC
}
Came across this thread and came up with a nice solution to help all in the future.
Firstly create a custom UINavigationController
with a type enum
that will help define your navigation setups:
enum NavType: Int {
case light, medium, dark
}
class NavigationController: UINavigationController {
/*
Fetch the last controller in the navigation stack so the
ViewControllers can switch the navType
*/
var previousController: ViewController? {
if viewControllers.count > 1 {
return viewControllers[viewControllers.count-2] as? ViewController
}
return nil
}
var navType: NavType = .light {
didSet { updateNavType() }
}
override func viewDidLoad() {
super.viewDidLoad()
navigationBar.isTranslucent = false
layoutNavigationTheme()
}
func layoutNavigationTheme() {
switch navType {
case .dark:
view.backgroundColor = .white
navigationBar.backgroundColor = .black
navigationBar.barTintColor = .black
navigationBar.tintColor = .white
... // Set up as per enum
}
}
}
Then create a custom UIViewController
using the willMove(...
:
class ViewController: UIViewController {
var navType: NavType = .light
var navigation: NavigationController? {
return navigationController as? NavigationController
}
// Override willMove will fetch the last controller and set the navType
override func willMove(toParentViewController parent: UIViewController?) {
super.willMove(toParentViewController: parent)
if let navigation = navigation {
navigation.navType = navigation.previousController?.navType ?? .light
}
}
}
Then simply in your UIViewControllers, subclass your new ViewController
and set the navType
in the viewDidLoad
:
class MainController: ViewController {
override func viewDidLoad() {
super.viewDidLoad()
navType = .dark
}
}
You can make custom navigation bar for SecondVC. And call -popViewController method manually on back button click.
Another solution that works is overriding pushViewController(_ viewController: UIViewController, animated: Bool) and popViewController(animated: Bool) -> UIViewController? of UINavigationController.
class CustomNC : UINavigationController {
public override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
}
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nil, bundle: nil)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private var isCustomDesign: Bool {
return viewControllers.count == 1 && viewControllers[0] is MyCustomVC // Or any other condition
}
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
super.pushViewController(viewController, animated: animated)
if isCustomDesign {
navigationBar.barTintColor = UIColor.red
} else {
navigationBar.barTintColor = UIColor.green
}
}
override func popViewController(animated: Bool) -> UIViewController? {
let viewController = super.popViewController(animated: animated)
if isCustomDesign {
navigationBar.barTintColor = UIColor.red
} else {
navigationBar.barTintColor = UIColor.green
}
return viewController
}
}