如何获取iOS中NavigationBar默认高度(或maxY)及大/小标题状态下高度?
嘿,我来帮你搞定这个导航栏高度的问题!针对你提到的需求——获取UINavigationBar的默认高度(优先maxY值),还要区分普通标题和大标题状态,我整理了一套靠谱的解决方案,顺便帮你排查下之前frame.maxY返回值异常的原因。
先搞清楚核心问题:为什么直接取frame.maxY不对?
你遇到的返回值异常,大概率是这两个原因:
- 布局时机不对:
viewDidLoad时视图还没完成布局,viewWillAppear也可能因为导航栏动画(比如大标题展开/折叠)导致frame未更新; - 透明背景的影响:当你把导航栏设为透明时,
isTranslucent默认是true,此时导航栏的frame会包含状态栏区域(刘海屏就是24pt+导航栏本身高度),所以返回的maxY会比你预期的“导航栏本身高度”高很多。
分场景获取高度/MaxY值
1. 获取静态默认高度(不考虑动态变化)
如果你只是想知道系统默认的高度值,不用实时监听变化,可以用UINavigationBarAppearance来获取,这是iOS 13+最推荐的方式:
// 普通标题(compact)状态下的导航栏本身高度 let compactNavBarHeight = UINavigationBarAppearance().compactLayoutSize.height // 大标题(large)展开状态下的导航栏本身高度 let largeNavBarAppearance = UINavigationBarAppearance() largeNavBarAppearance.configureWithLargeTitle() let largeNavBarHeight = largeNavBarAppearance.layoutSize.height
系统默认值:普通标题是44pt,大标题展开是96pt。
2. 获取实时的MaxY值(相对于导航控制器的View)
如果你需要的是导航栏frame的maxY(也就是从导航控制器View顶部到导航栏底部的距离),要在布局完成后获取,比如viewDidAppear或者layoutSubviews中:
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 获取当前导航栏的maxY if let navBarFrame = navigationController?.navigationBar.frame { print("当前导航栏maxY: \(navBarFrame.maxY)") } // 如果需要区分屏幕顶部到导航栏底部的距离(包含状态栏),可以这么算: let statusBarHeight = UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0 let currentNavBarHeight = navigationController?.navigationBar.bounds.height ?? 0 let screenToNavBarBottom = statusBarHeight + currentNavBarHeight print("屏幕顶部到导航栏底部的距离: \(screenToNavBarBottom)") }
- 刘海屏普通标题:
maxY是68pt(24pt状态栏+44pt导航栏); - 刘海屏大标题展开:
maxY是120pt(24pt状态栏+96pt导航栏); - 非刘海屏的话,状态栏高度换成20pt即可。
3. 监听大标题折叠/展开的动态高度变化
如果你的页面支持大标题,需要实时获取折叠/展开状态下的高度,可以用KVO监听导航栏的bounds变化:
override func viewDidLoad() { super.viewDidLoad() // 开启大标题模式 navigationController?.navigationBar.prefersLargeTitles = true // 添加KVO监听 navigationController?.navigationBar.addObserver(self, forKeyPath: "bounds", options: [.new], context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "bounds", let navBar = object as? UINavigationBar { print("导航栏高度变化: \(navBar.bounds.height),当前maxY: \(navBar.frame.maxY)") } } deinit { // 记得移除监听 navigationController?.navigationBar.removeObserver(self, forKeyPath: "bounds") }
额外提醒
- 如果你自定义了导航栏的背景(比如Effect View),建议把Effect View的高度和导航栏的
bounds.height绑定,而不是硬编码,这样能适配所有状态; - iOS 13+不要用
UIApplication.shared.statusBarFrame获取状态栏高度,改用statusBarManager的方式,避免多场景下的兼容性问题。
内容的提问来源于stack exchange,提问作者Augusto Carmo
相关产品推荐
相关产品推荐

