如何以编程方式获取iOS状态栏的高度


277

我知道目前iPhone / iPad顶部的状态栏(带有时间,电池和网络连接)对于非视网膜屏幕是20像素,对于视网膜屏幕是40像素,但是为了将来证明我的应用程序,我希望无需硬编码值就能确定这一点。是否可以通过编程计算出状态栏的高度?

Answers:


506

[UIApplication sharedApplication].statusBarFrame.size.height。但是由于所有尺寸均以点为单位,而不是以像素为单位,因此状态栏的高度始终等于20。

更新。看到这个答案被认为是有帮助的,我应该详细说明。

实际上,状态栏的高度等于20.0f点,以下情况除外

  • 状态栏已被setStatusBarHidden:withAnimation:方法隐藏,其高度等于0.0f点;
  • 正如@Anton在此指出的那样,在Phone应用程序外部的来电过程中或在录音会话状态栏高度等于40.0f点时。

状态栏还会影响视图的高度。通常,视图的高度等于给定方向的屏幕尺寸减去状态栏高度。但是,如果在显示视图后为状态栏设置动画(显示或隐藏),则状态栏将更改其框架,而视图不会更改,则必须在状态栏动画之后(或在状态栏高度在动画开始时设置为最终值)。

更新2。还有一种面向用户界面的情况。状态栏不考虑方向值,因此,对于横向 - ,纵向模式下的状态栏高度值为[UIApplication sharedApplication].statusBarFrame.size.height(是,默认方向始终为纵向,无论您的应用程序info.plist说什么)。要确定不在和不可用时UI的当前方向,请使用。[UIApplication sharedApplication].statusBarFrame.size.widthUIViewControllerself.interfaceOrientation[UIApplication sharedApplication].statusBarOrientation

iOS7更新。即使状态栏的视觉样式发生了变化,它仍然存在,其框架的行为仍然相同。我分享的关于状态栏的唯一有趣发现-我分享:您UINavigationBar平铺背景也会平铺到状态栏,因此您可以实现一些有趣的设计效果,也可以只为状态栏着色。这也不会以任何方式影响状态栏的高度。

导航栏平铺的背景也平铺到状态栏


6
此方法产生1024(iOS7)
Marc

1
@MarcMosby,请参阅我的更新。记住了这个问题-感谢您。
Kyr Dunenkoff

2
是的,正如Marc在iOS7上指出的那样,它有时可以输出1024,有时可以输出20。因此,这不再是确定高度的可靠方法。我怀疑这是由于iOS 7状态栏的透明性造成的。可能是因为它首先进入了全屏状态,然后才调整其大小。因此,如果您在此过渡期间进行应用查询,则可能会得到错误的值。可能延迟调用此方法可能会在iOS 7上有所帮助
。– Deepak GM

1
在某些情况下,状态栏的高度可以为零。如果supportedInterfaceOrientations()返回UIInterfaceOrientation(错误的结果,但没有编译器错误)而不是UIInterfaceOrientationMask,并且显示并关闭了一个视图控制器,则状态栏的高度将变为零。
Cymric

5
同样在iPhone X上状态栏会更高。

98

与去马丁的建议,这个问题:获取iPhone状态栏高度

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);

这是不正确的。旋转设备时状态栏的高度不会改变。宽度可以,但是上面的代码没有显示宽度,也不是原始问题。
lehn0058

1
没错,“旋转设备时状态栏的高度不会改变”。但是,正如Ash回答的那样,“在横向模式下,您可能会发现宽度和高度被交换了”。上面的代码考虑了这一点。
ma11hew28

我现在也一直看到这个有趣的问题。在我看来,这似乎是苹果方面的一个错误,但仍然需要解决。
lehn0058 2014年

2
@ lehn0058不是错误,而是Apple内部处理标准的方式。它连接到窗口,并使用变换旋转该窗口。将statusBarFrame返回,作为转换前的值。
Leo Natan 2014年

1
作为属性,它看起来更好:Dvar statusBarHeight: CGFloat
Pablo A.

23

试试这个:

CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;

1
在不同方向返回的高度是不同的。太奇怪了
tGilani

1
是的,如果旋转是横向的,则[[UIApplication sharedApplication] statusBarFrame] .size.height和[[UIApplication sharedApplication] statusBarFrame] .size.width的值已切换。
冈蒂斯·特鲁兰兹

21

Swift 3或Swift 4:

UIApplication.shared.statusBarFrame.height

10

虽然状态栏通常高20pt,但在某些情况下可能是该值的两倍:

  • 当您正在通话时(这是很常见的情况);
  • 当录音笔,Skype或类似应用程序在后台使用麦克风时;
  • 当个人热点被激活时;

尝试一下,您会发现自己的。将高度硬编码为20pt通常会起作用,直到无效为止。

因此,我第二次使用H2CO3:

statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;

10

编辑 iOS 11找出放置视图内容顶部的方式是UIView的safeAreaLayoutGuideSee UIView Documentation

弃用的答案 如果您的目标是iOS 7+,则UIViewController的文档建议viewController的topLayoutGuide属性为您提供状态栏的底部或导航栏的底部(如果它也是可见的)。这可能是有用的,并且肯定比许多以前的解决方案要少。


5

不要忘记状态栏的框架将在屏幕的坐标空间中!如果以横向模式启动,则可能会发现宽度和高度已交换。如果支持横向,我强烈建议您使用此版本的代码:

CGRect statusBarFrame = [self.window convertRect:[UIApplication sharedApplication].statusBarFrame toView:view];

然后,您可以直接读取statusBarFrame的height属性。在这种情况下,“视图”应该是您希望在其中使用度量的视图,很可能是应用程序窗口的根视图控制器。

顺便说一句,状态栏不仅在通话过程中更高,如果故意隐藏状态栏,状态栏也可以为零。


这没有给我正确的身高。但是,我发现了对我
有用的

是的,现在这是很旧的代码,因此可能不再是有效的答案。就个人而言,由于自动布局,我不再需要检查状态栏的高度。
Ash Ash



1
    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
    }


0

我只是找到了一种方法,该方法不让您直接访问状态栏的高度,而是对其进行计算。

导航栏高度-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

@nambatee我认为它不再起作用,因为我使用的是iOS 11苹果使用safeAreaInsets
Henry Ngan


-6

使用以下单行代码,您可以获取任何方向的状态栏高度,以及是否可见

#define STATUS_BAR_HIGHT (
    [UIApplicationsharedApplication].statusBarHidden ? 0 : (
        [UIApplicationsharedApplication].statusBarFrame.size.height > 100 ?
            [UIApplicationsharedApplication].statusBarFrame.size.width :
            [UIApplicationsharedApplication].statusBarFrame.size.height
    )
)

它只是一个简单但非常有用的宏,只需尝试一下即可,无需编写任何其他代码

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.