I am attempting to animate the change to the title of a detail UITableViewController
that is embedded in a UINavigationController
.
These two Q&A on stack overflow seem most relevant...
- Animate nav bar title text change OP by Jordan H;
- Transition Navigation Bar Title, OP by Jacob
I've attempted a number of code variants, mostly following Ashley Mills answer and others based on his answer, but essentially I cannot seem to make the animation work!
Note writing in Swift 5 using Xcode 10.2.
I'm using a Master-Detail UITableViewController
setup to manage a list and the details of the items in that list.
I'm using Large Titles...
navigationController?.navigationBar.prefersLargeTitles = true
...and a search controller...
navigationItem.searchController = <<mySearchController>>
navigationItem.hidesSearchBarWhenScrolling = false
definesPresentationContext = true
...all set in the viewDidLoad()
method for the Master View Controller.
Here's what I've done.
In my project:
import QuartzCore framework, per the comment by Jack Bellis "you'll need to add the QuartzCore framework via [project]>[target]>Build Phases>Link Binaries>QuartzCore.framework.";
In the Master View Controller:
import QuartzCore
;In the Detail View Controller:
In the
viewDidAppear(_ animated: Bool)
method, write theCATransition
code similar to the answers to the OP noted above (which changes the Large Title, but without animation).override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let animationTransition = CATransition() animationTransition.duration = 2.0 animationTransition.type = CATransitionType.push animationTransition.subtype = CATransitionSubtype.fromTop navigationController!.navigationBar.layer.add(animationTransition, forKey: "pushText") navigationItem.title = <<NEW TITLE TEXT>> }
In the
viewDidAppear(_ animated: Bool)
method, write alternatives to theCATransition
code suggested in the answers to the OP noted above (which only adds a separate title into the centre of the navigation bar and does not change the Large Title).override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let animationTransition = CATransition() animationTransition.duration = 2.0 animationTransition.type = CATransitionType.fade let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 44)) label.text = <<NEW TITLE TEXT>> navigationItem.titleView = label navigationItem.titleView!.layer.add(animationTransition, forKey: "fadeText") }
I've also tried including
CAMediaTimingFunction
...animationTransition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
I've also tried calling
setNeedsLayout
andsetNeedsDisplay
...navigationItem.titleView?.setNeedsLayout() navigationController?.navigationBar.setNeedsDisplay()
For clarity:
- the title text does change, but without animation;
- the code is written in the
viewDidAppear(_ animated:)
method, because I want the user to see the transition; - the duration is long (2 seconds) for testing - I may reduce this if/when the animation is working;
- Using the Inspectors in the storyboard, I've read through all the
UITableView
/Controller
andUINavigationController
settings to see whether I may have missed something.
Any suggestions?