Changing navigation bar color while popping view c

2020-02-25 02:48发布

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.

4条回答
我欲成王,谁敢阻挡
2楼-- · 2020-02-25 03:13

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
    }

}
查看更多
等我变得足够好
3楼-- · 2020-02-25 03:13

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
    }
}
查看更多
Juvenile、少年°
4楼-- · 2020-02-25 03:25

use this function in thiredVC

override func willMove(toParentViewController parent: UIViewController?) {
          self.navigationController?.navigationBar.barTintColor = color use in secondVC
    }
查看更多
Lonely孤独者°
5楼-- · 2020-02-25 03:25

You can make custom navigation bar for SecondVC. And call -popViewController method manually on back button click.

查看更多
登录 后发表回答