带大标题的UINavigationBar - 如何在iOS 11中找到额外的高度

SAH*_*AHM 3 uinavigationbar uinavigationcontroller ios ios11 large-title

当使用一个prefersLargeTitles UINavigationControllerUINavigationBariOS 11,导航栏增加高度.在我检查过的iPhone上增加了44到96,但我认为这些数字可以在每个设备上更改(或者至少我们需要编码,就好像它们可以).

我想以编程方式找到"额外"高度 - 在UINavigationBar显示大标题时添加到传统下方的大标题区域的高度.我可以很容易地找到显示大标题的栏的整个高度,但有没有办法以编程方式单独找到栏的大标题部分的高度(没有任何硬编码)?

我需要这个的原因是有时候我想以编程方式滚动到UITableView的顶部,拉下大标题(在"常规高度"导航栏下滚动)以便它显示,并且我需要的内容偏移是导航栏的额外高度.我可以使用导航栏的总高度,但这会将UITableView拉得太远.要做到这一点,我需要硬编码如下:

[self.tableView setContentOffset:CGPointMake(0, -52) animated:NO];
Run Code Online (Sandbox Code Playgroud)

Kam*_*ski 5

我想你找不到明确解决问题的方法.您要求的是导航栏内部的一部分,不向用户公开.但是,我想我可以为你提供一个解决方法.

要理解这一点,我们来看看视图调试器中的导航栏(启用了大型标题).正如您在下图所示,有一个额外的视图,包含特定视图控制器的大标题.如果不支持大型标题,则此视图不存在.

基本上,你想知道的是那个视图的高度.

导航栏的调试器预览

这是我提出的解决方案/解决方法

extension UINavigationBar
{
    var largeTitleHeight: CGFloat {
        let maxSize = self.subviews
            .filter { $0.frame.origin.y > 0 }
            .max { $0.frame.origin.y < $1.frame.origin.y }
            .map { $0.frame.size }
        return maxSize?.height ?? 0
    }
}
Run Code Online (Sandbox Code Playgroud)

它能做什么

  1. 过滤掉从导航栏顶部开始的子视图.它们很可能是背景或导航区域,我们不需要它们.
  2. 在导航栏中找到最低的子视图.
  3. 将生成的子视图帧映射到帧大小.
  4. 返回找到的子视图的高度,如果没有找到,则返回0.

这种方法的明显缺点是它与导航条的结构紧密耦合,可能在将来发生变化.但是,你不太可能获得超过一个或另一个肮脏的技巧.

执行结果应如下所示.

print("Extra height: \(navigationController!.navigationBar.lagreTitleHeight)")
Extra height: 52.0
Run Code Online (Sandbox Code Playgroud)