Cannot change style of UINavigationBar when using

2019-04-13 14:06发布

I have three view controllers embedded within a UINavigationController. FirstViewController navigates to SecondTableViewController, which navigates to ThirdDetailViewController.

The problem I am having is when customising the style of the status bar and UINavigationBar using the scrollViewDidScroll method within the SecondTableViewController it also override the other view controllers within the stack that come after it as well as all status bar styles.

Does anybody know how I can prevent the scrollViewDidScroll method from effecting other view controllers within the stack ?

FirstViewController

override func viewWillAppear(animated: Bool) {

UIApplication.sharedApplication().statusBarStyle = .Default
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarPosition: .Any, barMetrics: .Default)
self.navigationController?.navigationBar.shadowImage = UIImage()       
self.navigationController?.navigationBar.backgroundColor = UIColor.whiteColor()
self.navigationController?.navigationBar.tintColor = UIColor.blackColor()
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.translucent = true

}

SecondTableViewController

I change the style of the navigation depending on how far down the user has scrolled to either blend in or stand out from the content.

The style of other view controllers change to whichever style is set in the method.

 override func scrollViewDidScroll(scrollView: UIScrollView) {

    let color = colorWheel()

    if (scrollView.contentOffset.y > -60) {

        UIApplication.sharedApplication().statusBarStyle = .Default

        self.navigationController?.navigationBar.setBackgroundImage(nil, forBarMetrics: UIBarMetrics.Default)
        self.navigationController?.navigationBar.shadowImage = UIImage()
        self.navigationController?.navigationBar.backgroundColor = UIColor.whiteColor()
        self.navigationController?.navigationBar.tintColor = color.appColor
        self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
        self.navigationController?.view.backgroundColor = color.appColor
        self.navigationController?.navigationBar.translucent = true

    } else {

        UIApplication.sharedApplication().statusBarStyle = .LightContent

        self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
        self.navigationController?.navigationBar.shadowImage = UIImage()
        self.navigationController?.navigationBar.backgroundColor = UIColor.clearColor()
        self.navigationController?.navigationBar.tintColor = UIColor.whiteColor()
        self.navigationController?.navigationBar.barTintColor = UIColor.clearColor()
        self.navigationController?.view.backgroundColor = UIColor.clearColor()
        self.navigationController?.navigationBar.translucent = true
    }
}

ThirdDetailViewController

override func viewWillAppear(animated: Bool) {

UIApplication.sharedApplication().statusBarStyle = .Default
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarPosition: .Any, barMetrics: .Default)
self.navigationController?.navigationBar.shadowImage = UIImage()       
self.navigationController?.navigationBar.backgroundColor = UIColor.whiteColor()
self.navigationController?.navigationBar.tintColor = UIColor.blackColor()
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.translucent = true

}

2条回答
干净又极端
2楼-- · 2019-04-13 14:35

This is by (UIKit framework) design.

Your hierarchy is like this:

  • Navigation Controller (with a navigation bar)

hosting inside its stack

  • FirstViewController
  • SecondTableViewController
  • ThirdDetailViewController

Any UIViewController subclass that means also your controllers inherits a property called .navigationController. This simply points to whichever navigation controller hosts the view controller.

That means all three controllers you have point to THE SAME navigation controller. It's logical that it doesn't matter WHERE you do changes to .navigationController - because it's always the same and one and only navigation controller with one and only navigation bar, if you push or pop any view controller to the navigation stack, you will still see the latest styling you applied for the navigation bar.

The solution for you is to handle the navigation bar styling EXPLICITLY in EACH controller.

BONUS TRACK:

You can extract the navigation bar styling into a UIViewController extension. You could have a method called setNavigationStyle, define an enum NavigationStyle with some style cases, implement the style for each case inside the method, and then in any view controller inside viewWillAppear..just call setNavigationStyle: .Darkor whatever. This will scale nicely because you might have 3 style but 14 controllers. This way you prevent duplication of style implementation all over the place and make code reusable.

查看更多
做自己的国王
3楼-- · 2019-04-13 14:45

Change the Navigation properties from within the viewDidAppear method as well.

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

UIApplication.sharedApplication().statusBarStyle = .Default
UIApplication.sharedApplication().statusBarStyle = .Default
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarPosition: .Any, barMetrics: .Default)
self.navigationController?.navigationBar.shadowImage = UIImage()       
self.navigationController?.navigationBar.backgroundColor = UIColor.whiteColor()
self.navigationController?.navigationBar.tintColor = UIColor.blackColor()
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.translucent = true

}
查看更多
登录 后发表回答