如何以编程方式获取 iOS 状态栏高度
Posted
技术标签:
【中文标题】如何以编程方式获取 iOS 状态栏高度【英文标题】:How to programmatically get iOS status bar height 【发布时间】:2012-10-11 02:41:16 【问题描述】:我知道目前 iPhone/iPad 顶部的状态栏(包括时间、电池和网络连接)对于非视网膜屏幕是 20 像素,对于视网膜屏幕是 40 像素,但为了将来证明我的应用我希望能够在没有硬编码值的情况下确定这一点。是否可以通过编程方式计算状态栏的高度?
【问题讨论】:
【参考方案1】:[UIApplication sharedApplication].statusBarFrame.size.height
。但由于所有尺寸都以磅为单位,而不是以像素为单位,因此状态栏高度始终等于 20。
更新。看到这个答案被认为有帮助,我应该详细说明。
状态栏高度确实等于 20.0f 点除了以下情况:
状态栏已被setStatusBarHidden:withAnimation:
方法隐藏,高度为0.0f个点;
正如@Anton 在这里指出的那样,在电话应用程序之外的来电期间或在录音会话期间状态栏高度等于 40.0f 点。
还有一种情况是状态栏会影响视图的高度。通常,视图的高度等于给定方向的屏幕尺寸减去状态栏高度。但是,如果您在视图显示后为状态栏设置动画(显示或隐藏),状态栏将更改其框架,但视图不会,您必须在状态后手动调整视图大小条动画(或在动画期间,因为状态栏高度在动画开始时设置为最终值)。
更新 2。 还有一个用户界面方向的案例。状态栏不尊重方向值,因此 portrait 模式的状态栏高度值为[UIApplication sharedApplication].statusBarFrame.size.height
(是的,默认方向始终是纵向,无论您的应用程序 info.plist 说什么),对于 风景 - [UIApplication sharedApplication].statusBarFrame.size.width
。要在 UIViewController
和 self.interfaceOrientation
之外不可用时确定 UI 的当前方向,请使用 [UIApplication sharedApplication].statusBarOrientation
。
iOS7 更新。 尽管状态栏视觉样式发生了变化,但它仍然存在,它的框架仍然表现相同。我得到的关于状态栏的唯一有趣发现——我分享一下:你的UINavigationBar
的平铺背景也将平铺到状态栏上,这样你就可以实现一些有趣的设计效果或只是为你的状态栏着色.这也不会以任何方式影响状态栏的高度。
【讨论】:
此方法产生 1024 (ios7) @MarcMosby,查看我的更新。记住了这个问题 - 谢谢你。 是的,正如 Marc 在 iOS7 上指出的那样,它有时会产生 1024,有时会产生 20。因此,这不再是确定高度的万无一失的方法。我怀疑这是因为 iOS 7 上状态栏的透明性质。可能是它首先进入全屏,然后自行调整大小。因此,如果您在此转换期间应用查询,您可能会得到错误的值。可能会延迟调用此方法可能对 iOS 7 有所帮助。 存在状态栏高度可以为零的情况。如果supportedInterfaceOrientations() 返回UIInterfaceOrientation(不正确的结果但没有编译器错误)而不是UIInterfaceOrientationMask 并且一个viewcontroller 被呈现和关闭,状态栏高度将变为零。 同样在 iPhone X 上状态栏会更高。【参考方案2】:使用Martin's suggestion to the question: Get iPhone Status Bar Height。
CGFloat AACStatusBarHeight()
CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
return MIN(statusBarSize.width, statusBarSize.height);
在 Swift 中
func statusBarHeight() -> CGFloat
let statusBarSize = UIApplication.shared.statusBarFrame.size
return Swift.min(statusBarSize.width, statusBarSize.height)
这似乎是一个 hack,但实际上非常可靠。无论如何,这是唯一可行的解决方案。
旧答案
以下代码将放入您的UIViewController
的自定义子类中,几乎可以支持横向。但是,我注意到一个角落案例(当从右侧旋转 > 不受支持的倒置 > 向左旋转时)它不起作用(切换高度和宽度)。
BOOL isPortrait = self.interfaceOrientation == UIInterfaceOrientationPortrait;
CGSize statusBarSize = [UIApplication sharedApplication].statusBarFrame.size;
CGFloat statusBarHeight = (isPortrait ? statusBarSize.height : statusBarSize.width);
【讨论】:
这是不正确的。旋转设备时状态栏的高度不会改变。宽度会,但上面的代码没有显示,也不是原来的问题。 您说的对,“旋转设备时状态栏的高度不会改变”。但是,正如Ash answered,“在横向模式下,您可能会发现宽度和高度被交换了。”上面的代码考虑到了这一点。 这也是我现在看到的一个有趣的问题。对我来说,这似乎是苹果方面的一个错误,但仍需要考虑。 @lehn0058 这不是错误,这是 Apple 在内部处理栏的方式。它附加到一个窗口,并且该窗口使用变换进行旋转。statusBarFrame
作为转换前的值返回。
作为属性看起来更好:D var statusBarHeight: CGFloat
【参考方案3】:
试试这个:
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
【讨论】:
不同方向返回的高度不同。这很奇怪 是的,如果旋转是横向 - [[UIApplication sharedApplication] statusBarFrame].size.height 和 [[UIApplication sharedApplication] statusBarFrame].size.width 值被切换。【参考方案4】:Swift 3 或 Swift 4:
UIApplication.shared.statusBarFrame.height
【讨论】:
【参考方案5】:虽然状态栏通常是 20pt 高,但在某些情况下可能是这个高度的两倍:
当您正在打电话时(这是很常见的情况); 当录音机、Skype 或类似应用在后台使用麦克风时; 个人热点激活时;试试吧,你会亲眼看到的。将高度硬编码为 20pt 通常会起作用,直到不起作用。
所以我第二个 H2CO3 的答案:
statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
【讨论】:
【参考方案6】:编辑
iOS 11 确定视图内容顶部放置位置的方法是 UIView 的safeAreaLayoutGuide
请参阅UIView Documentation。
不推荐使用的答案
如果您的目标是 iOS 7+,UIViewController 的文档建议 viewController 的 topLayoutGuide
属性为您提供状态栏的底部,或者导航栏的底部,如果它也可见的话。这可能很有用,而且肯定比以前的许多解决方案更不被黑客攻击。
【讨论】:
【参考方案7】:对于 iOS 13,您可以使用:
UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame.height
【讨论】:
【参考方案8】:不要忘记状态栏的框架将在屏幕的坐标空间中!如果您在横向模式下启动,您可能会发现宽度和高度被交换了。如果您支持横向,我强烈建议您使用此版本的代码:
CGRect statusBarFrame = [self.window convertRect:[UIApplication sharedApplication].statusBarFrame toView:view];
然后您可以直接读取 statusBarFrame 的 height 属性。在这种情况下,“视图”应该是您希望在其中使用测量值的视图,很可能是应用程序窗口的根视图控制器。
顺便说一句,状态栏不仅可以在通话过程中更高,如果状态栏被故意隐藏,它也可以为零。
【讨论】:
这没有给我正确的高度。但是,我发现了对我有用的不同方式:***.com/a/16598350/242933 是的,现在这是相当老的代码,所以可能不再是一个有效的答案。就我个人而言,由于自动布局,我不再需要检查状态栏的高度。【参考方案9】: var statusHeight: CGFloat!
if #available(iOS 13.0, *)
statusHeight = UIApplication.shared.keyWindow?.windowScene?.statusBarManager?.statusBarFrame.height
else
// Fallback on earlier versions
statusHeight = UIApplication.shared.statusBarFrame.height
【讨论】:
【参考方案10】:这是获取屏幕状态栏高度的 Swift 方法:
var screenStatusBarHeight: CGFloat
return UIApplication.sharedApplication().statusBarFrame.height
这些作为标准功能包含在我的项目中:https://github.com/goktugyil/EZSwiftExtensions
【讨论】:
【参考方案11】:
UIApplication.shared.statusBarFrame.height
在 iOS 13 中已弃用
'statusBarFrame' 在 iOS 13.0 中已弃用:改用窗口场景的 statusBarManager 属性。
您可以在 iOS 13 中检索状态栏高度,如下所示:
let statusBarHeight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height
注意!它是可选的,因此请确保您有正确的后备。
【讨论】:
【参考方案12】:iOS 中默认状态栏高度为20 pt
。
更多信息:http://www.idev101.com/code/User_Interface/sizes.html
【讨论】:
除非不是。见上文。【参考方案13】:我刚刚找到了一种方法,让你不直接访问状态栏高度,而是计算它。
导航栏高度 - topLayoutGuide 长度 = 状态栏高度
斯威夫特:
let statusBarHeight = self.topLayoutGuide.length-self.navigationController?.navigationBar.frame.height
self.topLayoutGuide.length
是半透明条覆盖的顶部区域,self.navigationController?.navigationBar.frame.height
是不包括状态栏的半透明条,通常为44pt。所以通过这个方法,你可以轻松计算状态栏高度,而不必担心由于电话而导致的状态栏高度变化。
【讨论】:
这不起作用,self.topLayoutGuide.length
为 0,因此结果最终为 -44。
@nambatee 我相信它不再起作用了,因为我是 iOS 11 Apple 使用 safeAreaInsets【参考方案14】:
斯威夫特 5
UIApplication.shared.statusBarFrame.height
【讨论】:
您能否提供一些背景信息或解释为什么这会回答 OP 的问题?【参考方案15】:使用以下单行代码,您可以获得任何方向的状态栏高度,以及它是否可见
#define STATUS_BAR_HIGHT (
[UIApplicationsharedApplication].statusBarHidden ? 0 : (
[UIApplicationsharedApplication].statusBarFrame.size.height > 100 ?
[UIApplicationsharedApplication].statusBarFrame.size.width :
[UIApplicationsharedApplication].statusBarFrame.size.height
)
)
它只是一个简单但非常有用的宏,只需试试这个你不需要编写任何额外的代码
【讨论】:
以上是关于如何以编程方式获取 iOS 状态栏高度的主要内容,如果未能解决你的问题,请参考以下文章