I noticed another aspect of prefersLargeTitle
behavior that in some cases might provide even a simpler and more elegant solution. In my case, the viewController
contained not only the tableView
(otherwise I would simply use UITableViewController
and I would get standard prefersLargeTitle
behavior out-of-the-box), but also some other views. Now I noticed, that if you add the tableView
as a first subview of the viewController.view
, the table will control the large title feature:
// this will work
fileprivate func setupInitialHierarchy() {
self.view.addSubview(tableView)
self.view.addSubview(logoffButton)
}
Before I was creating the view hierarchy as follows:
// for some reason now the tableView will not control the large title
fileprivate func setupInitialHierarchy() {
self.view.addSubview(logoffButton)
self.view.addSubview(tableView)
}
So it seems that if the tableView
is the first subview of the viewController
s view
, we get the standard large titles behavior.
Alternative solution
However, if this is not possible, I have been able to simulate the standard behavior programmatically this way:
Implementing the delegate method for the tableView
that reacts to scrolling, and then running the code that uses current contentOffset
to either show, or hide the large title (UITableView
inherits from UIScrollView
, so the scrollView
parameter refers in this case to the tableView
):
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y <= 0 {
self.navigationItem.largeTitleDisplayMode = .always
} else {
self.navigationItem.largeTitleDisplayMode = .never
}
self.navigationController?.navigationBar.setNeedsLayout()
self.view.setNeedsLayout()
UIView.animate(withDuration: 0.25, animations: {
self.navigationController?.navigationBar.layoutIfNeeded()
self.view.layoutIfNeeded()
})
}
Just remember that scrollViewDidScroll
gets called repeatedly, so some guard
there might be desirable.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…