UINavigationBar 在推送时更改颜色
UINavigationBar change colors on push
我在 UINavigationBar
的不同视图中使用了 2 种不同的条形色调颜色。我在两个视图中都使用该方法更改颜色:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.barTintColor = COLOR
}
当我点击后退按钮时,颜色没有平滑变化(你可以看到最后一秒闪烁)。
但是如果只是向后滑动视图而不是点击后退按钮,一切都很好。
两种情况如何平滑过渡?
要实现这种动画,您应该使用 UIViewControllerTransitionCoordinator
作为 Apple documentation 说它是 :
An object that adopts the UIViewControllerTransitionCoordinator protocol provides support for animations associated with a view controller transition.(...)
所以每个 UIViewController
都有自己的 transitionController
。为此,您应该调用 UIViewControllerClass
:
self.transitionCoordinator()
来自 documentation:
Returns the active transition coordinator object.
因此,要获得您想要的结果,您应该在 viewController transitionCoordinatior 中实现 animateAlongsideTransition
方法。当您单击 backButton
并向后滑动时,动画会起作用。
示例:
第一个控制器:
class ViewControllerA: UIViewController {
override func loadView() {
super.loadView()
title = "A"
view.backgroundColor = .white
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "NEXT", style: .plain, target: self, action: #selector(self.showController))
setColors()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
animate()
}
func showController() {
navigationController?.pushViewController(ViewControllerB(), animated: true)
}
private func animate() {
guard let coordinator = self.transitionCoordinator else {
return
}
coordinator.animate(alongsideTransition: {
[weak self] context in
self?.setColors()
}, completion: nil)
}
private func setColors() {
navigationController?.navigationBar.tintColor = .black
navigationController?.navigationBar.barTintColor = .red
}
}
第二控制器:
class ViewControllerB : UIViewController {
override func loadView() {
super.loadView()
title = "B"
view.backgroundColor = .white
setColors()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
animate()
}
override func willMove(toParentViewController parent: UIViewController?) { // tricky part in iOS 10
navigationController?.navigationBar.barTintColor = .red //previous color
super.willMove(toParentViewController: parent)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.navigationBar.barTintColor = .blue
}
private func animate() {
guard let coordinator = self.transitionCoordinator else {
return
}
coordinator.animate(alongsideTransition: {
[weak self] context in
self?.setColors()
}, completion: nil)
}
private func setColors(){
navigationController?.navigationBar.tintColor = .black
navigationController?.navigationBar.barTintColor = .blue
}
}
更新iOS 10
在 iOS 10 中棘手的部分是在 second ViewController。并将 navigationBar tintColor
设置为 previous 控制器的颜色值。此外,在 second ViewControler 的 viewDidAppear
方法中,将 navigationBar.tintColor
的颜色设置为 秒viewController.
看看我的例子project on github
我编写了看起来使用起来最舒服的最终解决方案(不需要在自己的视图控制器中使用大量重写)。它在 iOS 10 时完美运行,并且易于为自己的目的采用。
GitHub
您可以查看 GitHub Gist 以获得完整的 class 代码和更详细的指南,我不会在此处 post 完整的代码,因为 Whosebug 不适合存储大量代码。
用法
为 GitHub 下载 Swift 文件。要使其正常工作,只需使用 ColorableNavigationController
而不是 UINavigationController
并将所需的子视图控制器采用 NavigationBarColorable
协议。
示例:
class ViewControllerA: UIViewController, NavigationBarColorable {
public var navigationBarTintColor: UIColor? { return UIColor.blue }
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Push", style: .plain, target: self, action: #selector(self.showController))
}
func showController() {
navigationController?.pushViewController(ViewControllerB(), animated: true)
}
}
class ViewControllerB: UIViewController, NavigationBarColorable {
public var navigationBarTintColor: UIColor? { return UIColor.red }
}
let navigationController = ColorableNavigationController(rootViewController: ViewControllerA())
我只是想知道。出于同样的目的,我使用 UINavigationControllerDelegate
。在 navigationController(_:willShow:)
中,我使用 transitionCoordinator?.animate(alongsideTransition:completion:)
启动动画。它在推动新控制器时效果很好,但 pop 却没有。
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
let dst = viewController as! ViewController
guard animated else {
navigationController.navigationBar.barTintColor = dst.navigationBarColor
navigationController.navigationBar.tintColor = dst.tintColor
navigationController.navigationBar.barStyle = dst.barStyle
return
}
navigationController.transitionCoordinator?.animate(alongsideTransition: { context in
navigationController.navigationBar.barTintColor = dst.navigationBarColor
navigationController.navigationBar.tintColor = dst.tintColor
navigationController.navigationBar.barStyle = dst.barStyle
}, completion: { context in
if context.isCancelled {
let source = context.viewController(forKey: UITransitionContextViewControllerKey.from) as! ViewController
navigationController.navigationBar.barTintColor = source.navigationBarColor
navigationController.navigationBar.tintColor = source.tintColor
navigationController.navigationBar.barStyle = source.barStyle
}
})
你有什么理由认为它应该适用于推送而不适用于弹出吗?
这对我有用:
override func willMove(toParent parent: UIViewController?) {
super.willMove(toParent: parent)
navigationController?.navigationBar.barTintColor = previous view controller's navigation bar color
}
我在 UINavigationBar
的不同视图中使用了 2 种不同的条形色调颜色。我在两个视图中都使用该方法更改颜色:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.barTintColor = COLOR
}
当我点击后退按钮时,颜色没有平滑变化(你可以看到最后一秒闪烁)。
但是如果只是向后滑动视图而不是点击后退按钮,一切都很好。
两种情况如何平滑过渡?
要实现这种动画,您应该使用 UIViewControllerTransitionCoordinator
作为 Apple documentation 说它是 :
An object that adopts the UIViewControllerTransitionCoordinator protocol provides support for animations associated with a view controller transition.(...)
所以每个 UIViewController
都有自己的 transitionController
。为此,您应该调用 UIViewControllerClass
:
self.transitionCoordinator()
来自 documentation:
Returns the active transition coordinator object.
因此,要获得您想要的结果,您应该在 viewController transitionCoordinatior 中实现 animateAlongsideTransition
方法。当您单击 backButton
并向后滑动时,动画会起作用。
示例:
第一个控制器:
class ViewControllerA: UIViewController {
override func loadView() {
super.loadView()
title = "A"
view.backgroundColor = .white
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "NEXT", style: .plain, target: self, action: #selector(self.showController))
setColors()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
animate()
}
func showController() {
navigationController?.pushViewController(ViewControllerB(), animated: true)
}
private func animate() {
guard let coordinator = self.transitionCoordinator else {
return
}
coordinator.animate(alongsideTransition: {
[weak self] context in
self?.setColors()
}, completion: nil)
}
private func setColors() {
navigationController?.navigationBar.tintColor = .black
navigationController?.navigationBar.barTintColor = .red
}
}
第二控制器:
class ViewControllerB : UIViewController {
override func loadView() {
super.loadView()
title = "B"
view.backgroundColor = .white
setColors()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
animate()
}
override func willMove(toParentViewController parent: UIViewController?) { // tricky part in iOS 10
navigationController?.navigationBar.barTintColor = .red //previous color
super.willMove(toParentViewController: parent)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.navigationBar.barTintColor = .blue
}
private func animate() {
guard let coordinator = self.transitionCoordinator else {
return
}
coordinator.animate(alongsideTransition: {
[weak self] context in
self?.setColors()
}, completion: nil)
}
private func setColors(){
navigationController?.navigationBar.tintColor = .black
navigationController?.navigationBar.barTintColor = .blue
}
}
更新iOS 10
在 iOS 10 中棘手的部分是在 second ViewController。并将 navigationBar tintColor
设置为 previous 控制器的颜色值。此外,在 second ViewControler 的 viewDidAppear
方法中,将 navigationBar.tintColor
的颜色设置为 秒viewController.
看看我的例子project on github
我编写了看起来使用起来最舒服的最终解决方案(不需要在自己的视图控制器中使用大量重写)。它在 iOS 10 时完美运行,并且易于为自己的目的采用。
GitHub
您可以查看 GitHub Gist 以获得完整的 class 代码和更详细的指南,我不会在此处 post 完整的代码,因为 Whosebug 不适合存储大量代码。
用法
为 GitHub 下载 Swift 文件。要使其正常工作,只需使用 ColorableNavigationController
而不是 UINavigationController
并将所需的子视图控制器采用 NavigationBarColorable
协议。
示例:
class ViewControllerA: UIViewController, NavigationBarColorable {
public var navigationBarTintColor: UIColor? { return UIColor.blue }
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Push", style: .plain, target: self, action: #selector(self.showController))
}
func showController() {
navigationController?.pushViewController(ViewControllerB(), animated: true)
}
}
class ViewControllerB: UIViewController, NavigationBarColorable {
public var navigationBarTintColor: UIColor? { return UIColor.red }
}
let navigationController = ColorableNavigationController(rootViewController: ViewControllerA())
我只是想知道。出于同样的目的,我使用 UINavigationControllerDelegate
。在 navigationController(_:willShow:)
中,我使用 transitionCoordinator?.animate(alongsideTransition:completion:)
启动动画。它在推动新控制器时效果很好,但 pop 却没有。
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
let dst = viewController as! ViewController
guard animated else {
navigationController.navigationBar.barTintColor = dst.navigationBarColor
navigationController.navigationBar.tintColor = dst.tintColor
navigationController.navigationBar.barStyle = dst.barStyle
return
}
navigationController.transitionCoordinator?.animate(alongsideTransition: { context in
navigationController.navigationBar.barTintColor = dst.navigationBarColor
navigationController.navigationBar.tintColor = dst.tintColor
navigationController.navigationBar.barStyle = dst.barStyle
}, completion: { context in
if context.isCancelled {
let source = context.viewController(forKey: UITransitionContextViewControllerKey.from) as! ViewController
navigationController.navigationBar.barTintColor = source.navigationBarColor
navigationController.navigationBar.tintColor = source.tintColor
navigationController.navigationBar.barStyle = source.barStyle
}
})
你有什么理由认为它应该适用于推送而不适用于弹出吗?
这对我有用:
override func willMove(toParent parent: UIViewController?) {
super.willMove(toParent: parent)
navigationController?.navigationBar.barTintColor = previous view controller's navigation bar color
}