+ (CGFloat)statusBarHeight {
if ( @available(iOS 13.0, *)) {
NSSet *set = [UIApplication sharedApplication].connectedScenes;
UIWindowScene *windowScene = [set anyObject];
UIStatusBarManager *statusBarManager = windowScene.statusBarManager;
CGFloat statusBarHeight = statusBarManager.statusBarFrame.size.height;
if( @available(iOS 16.0, *)) {
BOOL needAdjust = (statusBarHeight == 44);
if(windowScene.windows.firstObject.safeAreaInsets.top == 59 && needAdjust) {
statusBarHeight = 59;
}
}
return statusBarHeight;
}
CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
CGFloat safeAreaTop = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets.top;
return MAX(statusBarHeight, safeAreaTop);
}
Answer from Pix1O on Stack Overflow+ (CGFloat)statusBarHeight {
if ( @available(iOS 13.0, *)) {
NSSet *set = [UIApplication sharedApplication].connectedScenes;
UIWindowScene *windowScene = [set anyObject];
UIStatusBarManager *statusBarManager = windowScene.statusBarManager;
CGFloat statusBarHeight = statusBarManager.statusBarFrame.size.height;
if( @available(iOS 16.0, *)) {
BOOL needAdjust = (statusBarHeight == 44);
if(windowScene.windows.firstObject.safeAreaInsets.top == 59 && needAdjust) {
statusBarHeight = 59;
}
}
return statusBarHeight;
}
CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
CGFloat safeAreaTop = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets.top;
return MAX(statusBarHeight, safeAreaTop);
}
Please try the below solution. Working for iPhone 14 Pro and iPhone 14 max Pro.
if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.first
let topPadding = window?.safeAreaInsets.top
let statusBar = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: topPadding ?? 0.0))
statusBar.backgroundColor = UIColor(named: "AppPrimaryColor")
UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.addSubview(statusBar)
}
Hope this will solve your issue. Keep coding :)
[UIApplication sharedApplication].statusBarFrame.size.height. But since all sizes are in points, not in pixels, status bar height always equals 20.
Update. Seeing this answer being considered helpful, I should elaborate.
Status bar height is, indeed, equals 20.0f points except following cases:
- status bar has been hidden with
setStatusBarHidden:withAnimation:method and its height equals 0.0f points; - as @Anton here pointed out, during an incoming call outside of Phone application or during sound recording session status bar height equals 40.0f points.
There's also a case of status bar affecting the height of your view. Normally, the view's height equals screen dimension for given orientation minus status bar height. However, if you animate status bar (show or hide it) after the view was shown, status bar will change its frame, but the view will not, you'll have to manually resize the view after status bar animation (or during animation since status bar height sets to final value at the start of animation).
Update 2. There's also a case of user interface orientation. Status bar does not respect the orientation value, thus status bar height value for portrait mode is [UIApplication sharedApplication].statusBarFrame.size.height (yes, default orientation is always portrait, no matter what your app info.plist says), for landscape - [UIApplication sharedApplication].statusBarFrame.size.width. To determine UI's current orientation when outside of UIViewController and self.interfaceOrientation is not available, use [UIApplication sharedApplication].statusBarOrientation.
Update for iOS7. Even though status bar visual style changed, it's still there, its frame still behaves the same. The only interesting find about status bar I got – I share: your UINavigationBar's tiled background will also be tiled to status bar, so you can achieve some interesting design effects or just color your status bar. This, too, won't affect status bar height in any way.
Go with 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);
}
And in Swift
func statusBarHeight() -> CGFloat {
let statusBarSize = UIApplication.shared.statusBarFrame.size
return Swift.min(statusBarSize.width, statusBarSize.height)
}
It seems like a hack, but it's actually pretty solid. Anyway, it's the only working solution.
Old Answer
The following code, which would go in your custom subclass of UIViewController, almost worked to support landscape. But, I noticed a corner case (when rotating from right > unsupported upside-down > left) for which it didn't work (switched height & width).
BOOL isPortrait = self.interfaceOrientation == UIInterfaceOrientationPortrait;
CGSize statusBarSize = [UIApplication sharedApplication].statusBarFrame.size;
CGFloat statusBarHeight = (isPortrait ? statusBarSize.height : statusBarSize.width);
You should never hardcode the exact value of the height at any point in your code.
As long as you use default UI components (UINavigationController / UITableView / UICollectionView / etc.) you usually don't need to worry about the status bar height at all. These ViewControllers should layout correctly on any device and any orientation.
If you do have custom layout needs, you should refer to the safeAreaLayoutGuide on UIView, instead of hardcoding a height:
https://developer.apple.com/documentation/uikit/uiview/2891102-safearealayoutguide?language=objc
But to make this answer complete - the size of the status bar is different on different devices and different orientations:
- Most devices up to the iPhone X have a 20pt height in portrait & landscape.
(20px, 40px, 60px in @1x, @2x, @3x) - On iPhone X in portrait it's 44pt (so 44px, 88px, 132px accordingly).
In landscape the height is different though.
Your parent view controller will resize it's view to the right size. You can
- make your view controller load a subclass of UIView and override
-layoutSubviews - insert your subview with the proper starting size (
[[ MyViewClass alloc ] initWithFrame:superview.bounds]) and the proper autoresizing mask. It's important when using autoresizing struts & springs that you give your view the proper size to start with.
BTW--another problem with hard coding the status bar height: it's sometimes double-height. (when the user is recording audio, making a phone call, using internet tethering, using navigation, etc.)
Just wondering if I can use the Status Bar height from different iPhones (which tends to be around 52–54px) instead of the top inset provided by SafeAreaView (which tends to be around 60–62px).
For context, see the image attached above. I’m willing to design my project within the 54 points related to the Status Bar on this iPhone 16 Pro, but I don’t want to hardcode it since different iPhones have different sizes.
I know this sounds like it’s not important for the end result (which is true), but I come from a design background and I’m trying to get a pixel-perfect layout compared to what I usually design in Figma. I couldn’t find anything on this here or anywhere else.
What I’ve discovered is that native apps like Airbnb seem to use the Status Bar instead of the Safe Area, which is one of the reasons I want to perfect this approach.
Thanks in advance!
As the warning hints, you can access the statusBarManager which has a statusBarFrame property. This is defined on your UIWindow's windowScene.
let height = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
Try, I have tried it.
let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
let height = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
If you're using Expo you can use Constants.statusBarHeight.
import Constants from 'expo-constants';
const statusBarHeight = Constants.statusBarHeight;
If you're using Vanilla React Native with React Navigation you can use the following:
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const insets = useSafeAreaInsets();
const statusBarHeight = insets.top;
See: https://reactnavigation.org/docs/handling-safe-area/#use-the-hook-for-more-control
Sample Code:
import * as React from 'react';
import { Text, View, StatusBar } from 'react-native';
import Constants from 'expo-constants';
import { useSafeAreaInsets, SafeAreaProvider } from 'react-native-safe-area-context';
export default function App() {
return (
<SafeAreaProvider>
<ChildScreen />
</SafeAreaProvider>
);
}
function ChildScreen() {
const insets = useSafeAreaInsets();
return (
<View style={{ flex: 1, justifyContent: 'center'}}>
<Text>
{insets.top}
</Text>
<Text>
{Constants.statusBarHeight}
</Text>
<Text>
{StatusBar.currentHeight ?? 'N/A'}
</Text>
</View>
);
}
Output:
| Samsung Galaxy S10 5G | iPhone 8 Plus | iPhone 11 Pro Max | Web | |
|---|---|---|---|---|
insets.top |
39.71428680419922 | 20 | 44 | 0 |
Constants.statusBarHeight |
39 | 20 | 44 | 0 |
StatusBar.currentHeight ?? 'N/A' |
39.42856979370117 | N/A | N/A | N/A |
Live code: https://snack.expo.dev/@dcangulo/statusbarheight
You can use React Navigation that already have support of iPhone X.
Even if you don't want use this library because of some reason - you still can read source code to copy implementation in your code