如何在iOS 11的navigationBar中模仿UITableViewController大标题的显示 [英] How to mimic `UITableViewController` showing of the large titles in `navigationBar` on iOS 11
问题描述
我正在尝试在我的应用程序中使用iOS 11中的 prefersLargeTitles
.它在 UITableViewController
的子类中按预期工作:
navigationController?.navigationBar.prefersLargeTitles = true
但是,在一种情况下,我需要继承 UIViewController
并自己添加一个表视图.在这种情况下,我需要将表约束为自己查看:
tableView.topAnchor.constraint(equalTo:self.view.safeAreaLayoutGuide.topAnchor).isActive = truetableView.leftAnchor.constraint(equalTo:self.view.leftAnchor).isActive = truetableView.rightAnchor.constraint(equalTo:self.view.rightAnchor).isActive = truetableView.bottomAnchor.constraint(equalTo:self.otherView.topAnchor).isActive = true
尽管这些约束像我期望的那样显示了 tableView
,但现在导航栏始终使用大标题.我想模仿 UITableViewController
的行为,以便当 tableView
滚动到顶部时,会显示较大的标题,否则标题会折叠为普通标题.
如何解决这个问题?
我注意到 prefersLargeTitle
行为的另一个方面,在某些情况下,它甚至可以提供更简单,更优雅的解决方案.就我而言, viewController
不仅包含 tableView
(否则,我将只使用 UITableViewController
,而我将获得标准的 prefersLargeTitle 代码>行为),还有其他一些视图.现在我注意到,如果将
tableView
添加为 viewController.view
的第一个子视图,则该表将控制大标题功能:
//这将起作用fileprivate func setupInitialHierarchy(){self.view.addSubview(tableView)self.view.addSubview(logoffButton)}
在创建视图层次结构之前,如下:
//由于某种原因现在tableView将无法控制大标题fileprivate func setupInitialHierarchy(){self.view.addSubview(logoffButton)self.view.addSubview(tableView)}
所以看来,如果 tableView
是 viewController
的 view
的第一个子视图,我们将获得标准的大标题行为./p>
替代解决方案
但是,如果不可能,我已经可以通过这种方式以编程方式模拟标准行为:
为可响应滚动的 tableView
实施委托方法,然后运行使用当前 contentOffset
的代码来显示或隐藏大标题( UITableView
继承自 UIScrollView
,因此 scrollView
参数在这种情况下指的是 tableView
):
func scrollViewDidScroll(_ scrollView:UIScrollView){如果scrollView.contentOffset.y< = 0 {self.navigationItem.largeTitleDisplayMode =.始终} 别的 {self.navigationItem.largeTitleDisplayMode = .never}self.navigationController?.navigationBar.setNeedsLayout()self.view.setNeedsLayout()UIView.animate(withDuration:0.25,动画:{self.navigationController?.navigationBar.layoutIfNeeded()self.view.layoutIfNeeded()})}
请记住, scrollViewDidScroll
会被反复调用,因此可能需要一些 guard
.
I'm trying to use prefersLargeTitles
from iOS 11 in my application. It works as expected in subclasses of UITableViewController
:
navigationController?.navigationBar.prefersLargeTitles = true
However, in one case I needed to subclass UIViewController
and add a table view myself. In this situation I needed to constraint the table to the view myself:
tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: self.otherView.topAnchor).isActive = true
While these constraints present the tableView
as I would expect, now the navigation bar always uses large title. I would like to mimic the behavior of the UITableViewController
, so that when the tableView
is scrolled to top, the large title is presented, otherwise the title collapses into the normal one.
How to solve this?
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.
这篇关于如何在iOS 11的navigationBar中模仿UITableViewController大标题的显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!