I have been searching for how to transition/animate the barTintColor
of a UINavigationBar
for a while now, and I only see different answers. Some use UIView.animateWithDuration
, some use CATransition
, but the most interesting ones, like this one use animate(alongsideTransition animation..
, which I like the sound of, but I can't get it working properly. Am I doing something wrong?
Many specify that I can simply use the transitionCoordinator
in viewWillAppear:
. I have set up a fresh super tiny project like this:
class RootViewController:UIViewController{ //Only subclassed
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in
self?.setNavigationColors()
}, completion: nil)
}
func setNavigationColors(){
//Override in subclasses
}
}
class FirstViewController: RootViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "First"
}
override func setNavigationColors(){
navigationController?.navigationBar.barTintColor = UIColor.white
navigationController?.navigationBar.tintColor = UIColor.black
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.black]
navigationController?.navigationBar.barStyle = UIBarStyle.default
}
}
class SecondViewController: RootViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Second"
}
override func setNavigationColors(){
navigationController?.navigationBar.barTintColor = UIColor.black
navigationController?.navigationBar.tintColor = UIColor.white
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
navigationController?.navigationBar.barStyle = UIBarStyle.black
}
}
With this code, this happens:
- The push-transition from
First
toSecond
looks perfect. All elements transition perfectly, maybe except the StatusBar, which instantly changes to white. I'd rather know how to transition it, but I'll accept it for now. - The pop-transition from
Second
toFirst
is completely wrong. It keeps the colors fromSecond
until the transition is completely done. - The drag-transition from
Second
toFirst
looks alright, when dragging all the way over. Again, the StatusBar instantly becomes black as soon as I start dragging, but I don't know if that's possible to fix. - The drag-transition from
Second
toFirst
but cancelled mid-drag and returning toSecond
is completely screwed up. It looks fine untilSecond
is completely back in control, and then it suddenly changes itself toFirst
-colors. This should not happen.
I made a few changes to my RootViewController
to make it a little better. I removed viewWillAppear:
completely, and changed it with this:
class RootViewController:UIViewController{
override func willMove(toParentViewController parent: UIViewController?) {
if let last = self.navigationController?.viewControllers.last as? RootViewController{
if last == self && self.navigationController!.viewControllers.count > 1{
if let parent = self.navigationController!.viewControllers[self.navigationController!.viewControllers.count - 2] as? RootViewController{
parent.setNavigationColors()
}
}
}
}
override func viewWillDisappear(_ animated: Bool) {
if let parent = navigationController?.viewControllers.last as? RootViewController{
parent.animateNavigationColors()
}
}
override func viewDidAppear(_ animated: Bool) {
self.setNavigationColors()
}
func animateNavigationColors(){
transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in
self?.setNavigationColors()
}, completion: nil)
}
func setNavigationColors(){
//Override in subclasses
}
}
With this updated code, I get this:
A few observations:
- The transition from
First
toSecond
is the same - The pop-transition from
Second
toFirst
is now animating correctly, except from the back-arrow, the back-text (and the statusBar, but yeah..). These are instantly changed to black. In the first gif, you could see that the back-arrow and the back-text also transitioned. - The drag-transition from
Second
toFirst
also has this problem, the back-arrow and back-text are suddenly instantly black when starting. The barTint is fixed so that it doesn't get the wrong color when cancelling the drag.
What am I doing wrong? How am I supposed to do this?
What I want is to transition all elements smoothly. The tint of the back-button, the back-text, the title, the barTint, and the statusBar. Is this not possible?