This was a great answer but it took some tweaking for me to get it right.
So the general idea is that you have a text in the middle of your scrollView and when the user scrolls up past that text then you want it to become the new title. Furthermore, when you scroll back down, you want it to change back to the default title.


So, using the code that Gix posted, now converted to Swift 3, here's how you get it done.
Add these variables to the top of your viewController
var didChangeTitle = false
let defaultTitle = "Default Title"
let animateUp: CATransition = {
let animation = CATransition()
animation.duration = 0.5
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromTop
animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
return animation
}()
let animateDown: CATransition = {
let animation = CATransition()
animation.duration = 0.5
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromBottom
animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
return animation
}()
In your viewDidLoad, add this code to set the default title.
let titleLabelView = UILabel.init(frame: CGRect(x: 0, y: 0, width: 200, height: 44))
titleLabelView.backgroundColor = .clear
titleLabelView.textAlignment = .center
titleLabelView.textColor = UINavigationBar.appearance().tintColor
titleLabelView.font = UIFont.boldSystemFont(ofSize: 16)
titleLabelView.text = defaultTitle
self.navigationItem.titleView = titleLabelView
Now you add some code to your scrollView delegate function:
extension MyViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y >= (labelName.frame.origin.y + labelName.frame.height) && !didChangeTitle {
if let label = navigationItem.titleView as? UILabel {
label.layer.add(animateUp, forKey: "changeTitle")
label.text = labelName.text
}
didChangeTitle = true
} else if scrollView.contentOffset.y < labelName.frame.origin.y && didChangeTitle {
if let label = navigationItem.titleView as? UILabel {
label.layer.add(animateDown, forKey: "changeTitle")
label.text = defaultTitle
}
didChangeTitle = false
}
}
}
The "labelName" var is the label in your scrollview that contains your future title.