In case somebody needs this. Here is how I did it. For me, this is better than the default, because it supports whatever customization you may want from large title (ex. multiline)
In my case my layout looks like this. You can have however you want, but make sure title is not inside of the table view / scroll view.
view
- view
- large title label
- view (this view will stick on top)
- view
- view
In this case, I have scrollViewDidScroll delegate, which checks the scrollView content offset to change the titleLabels top constraint. For me top constraint is 16. Change it to whatever you want to have
extension YourViewController: UITableViewDelegate {
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
let titleHeight = titleLabel.bounds.height
if (scrollView.contentOffset.y <= 0) {
// Title is fully visible - table view is at the top
titleLabelTopConstraint.constant = 16
isLargeTitleHidden = false
} else if (scrollView.contentOffset.y > (titleHeight + 16)){
// Title is not visible at all. Table view is at an unknown position but it is not top
titleLabelTopConstraint.constant = -titleHeight
isLargeTitleHidden = true
} else {
// Title is kind of visible. Not fully hidden or shown.
titleLabelTopConstraint.constant = -scrollView.contentOffset.y + 16
isLargeTitleHidden = false
}
} }
I also have the isLargeTitleHidden to update the nav
var isLargeTitleHidden: Bool = false {
didSet{
if (oldValue != isLargeTitleHidden){
updateNavBar()
}
}
}
func updateNavBar(){
let fadeTextAnimation = CATransition()
fadeTextAnimation.duration = 0.2
fadeTextAnimation.type = CATransitionType.fade
navigationController?.navigationBar.layer.add(fadeTextAnimation, forKey: "fadeText")
if isLargeTitleHidden {
navigationItem.title = titleLabel.text
} else {
navigationItem.title = ""
}
}