上下文
假设我们有一个NavigationController
和两个viewControllers。
ViewControllerA
有一个蓝色的navigationBar,而ViewControllerB
有一个绿色的。
我这样设置:
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.barTintColor = UIColor.blue // Green if ViewController B
}
当我从A到B时,它运作良好,但是当我返回时,navigationBar teint会在之后更新。就像它是在viewDidAppear
中设置的那样。
预期:
导航栏的导航栏颜色应立即更新。
已尝试解决方案:
我看过这篇SO帖子,我尝试了解决方案。它有效,但会使导航栏的管理变得更加复杂和痛苦。 (在一个真实的应用程序中)
我尝试在ViewWillDisappear
方法中更改导航栏提示。没用。
更多:
这是由ios10 API的更改引起的。我已经阅读了release notes,但目前还不清楚在这种情况下应该做些什么。
在iOS 10中,UIKit已经更新并统一了后台管理 UINavigationBar,UITabBar和UIToolbar。特别是改变了 这些视图的背景属性(例如背景或阴影 图像,或设置栏样式)可以启动布局传递 栏来解决新的背景外观。
特别是这个 意味着尝试更改这些条的背景外观 在layoutSubviews中, - [UIView updateConstraints], viewWillLayoutSubviews,viewDidLayoutSubviews,updateViewConstraints, 或者可能导致响应布局而调用的任何其他方法 布局循环。
在某些情况下,您可以通过确保您来打破这些布局循环 在对象(例如UIImage或。)时始终使用相同的对象实例 UIColor)是必需的。但总的来说,你应该避免这样做。
问题:
在iOS 10中处理不同导航控制器之间导航栏更改的最佳方法是什么?
答案 0 :(得分:11)
试试这段代码:
注意:代码在Swift 3中测试。
在ViewController A中:
override var isViewLoaded: Bool {
title = "View 1"
navigationController?.navigationBar.barTintColor = .blue
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.tintColor = UIColor.white
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white]
UIApplication.shared.statusBarStyle = .lightContent
self.navigationController?.navigationBar.barStyle = .black // In case statusbar Light content wont work.
return true
}
在ViewController B中:
override var isViewLoaded: Bool {
title = "View 2"
navigationController?.navigationBar.barTintColor = .green
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white]
return true
}
输出:没有任何延迟......
图案图片为TintColor。
在ViewController A中:
navigationController?.navigationBar.barTintColor = UIColor(patternImage: UIImage(named: "viewOneImage.jpg")!)
在ViewController B中:
navigationController?.navigationBar.barTintColor = UIColor(patternImage: UIImage(named: "viewTwoImage.jpg")!)
输出:
答案 1 :(得分:0)
我对覆盖isViewLoaded
的解决方案不满意,因为如果有时间显示view_controller_a
,并且出于任何原因使用view_controller_b.isViewLoaded
的值,那么您将结束向上将导航栏更改为错误的显示。
相反,我会将所需的导航栏配置存储在每个视图控制器中,并使用UINavigationControllerDelegate
:
class NavBarConfig
{
var background_color: UIColor
init( background_color: UIColor )
{
self.background_color = background_color
}
}
class ViewController: UIViewController
{
var nav_bar_config: NavBarConfig?
}
class NavControllerDelegate: UINavigationControllerDelegate
{
//Called just before the navigation controller displays a view controller’s view and navigation item properties.
func navigationController( _ nav_controller: UINavigationController, willShow view_controller: UIViewController, animated: Bool )
{
if let view_controller = view_controller as? ViewController, let nar_bar_config = view_controller.nav_bar_config
{
nav_controller.navigationBar.barTintColor = view_controller.nar_bar_config.background_color
}
}
}
在导航控制器your_nav_controller.delegate = NavControllerDelegate()
上设置委托后,将在显示每个视图控制器之前调用委托方法,使您可以按自己的意愿配置导航栏。