StatusBar.currentHeight
is Android only (e.g. 49.14285659790039 on Pixel 3 XL with a notch), return null
on iOSConstants.statusBarHeight
from expo-constants
works on both iOS and Android. (e.g. 20 on iPhone 5, 49 on Pixel 3 XL with a notch )backgroundColor
is also Android onlyStatusBar
needs to be outside of the SafeArea
for it to render properlySafeArea
excludes the StatusBar
. If you don’t use a SafeArea
, the view will get inside the StatusBar
translucent
on the status bar to make it behave consistently on iOS and Android. Doing so will make your life easier. Not doing so will means you’ll always add Platform specific code.The height is pretty much always 20
, unless it’s hidden or an app is active during an incoming call, in which case it is 40
points. Except iPhone X and iPhone 11 are different because they have notches..
On iOS, your app will draw under the status bar. On Android, the app draws on top of the status bar. You can achieve similar behaviour for Android by setting translucent
(Android only)
1<StatusBar translucent={true} backgroundColor={'transparent'} {...props} />
If we set translucent={true}
on StatusBar
then it’d behave consistently on both iOS and Adnroid, and you wouldn’t have to set different values for things like padding
and height
in a custom header using Platform checks
Since backgroundColor
is also Android only, you can not use it to set the background color for StatusBar in iOS.
What you can do instead is use the status bar inside a View that has padding at the top (equivalent to the height of status bar) and has a background color.
1<StatusBarBackground>
2 <StatusBar barStyle="light-content" />
3 <SafeAreaView>{/* Code goes here */}</SafeAreaView>
4</StatusBarBackground>
1import Constants from 'expo-constants'
2
3const headerHeight = 48
4
5const StatusBarBackground = styled.View`
6 background: salmon;
7 padding-top: ${Platform.OS === 'ios' ? Constants.statusBarHeight : 0}px;
8 height: ${Platform.OS === 'ios' ? Constants.statusBarHeight + headerHeight : headerHeight}px;
9`
Notice that you had to keep the padding and height Platform specific. Because on iOS the status bar draws under the status bar, we are only adding extra padding on iOS. On Android, we can pass backgroundColor
to the <StatusBar>
, and the default behaviour for the app is to draw over the status bar. This can be avoided if we set translucent={true}
on StatusBar
, and then it’d behave consistently on both iOS and Android. By default translucent
is false
on Android
1<StatusBarBackground>
2 <StatusBar translucent barStyle="light-content" />
3 <SafeAreaView>{/* Code goes here */}</SafeAreaView>
4</StatusBarBackground>
1import Constants from 'expo-constants'
2
3const headerHeight = 48
4
5const StatusBarBackground = styled.View`
6 background: salmon;
7 padding-top: ${Constants.statusBarHeight}px;
8 height: ${Constants.statusBarHeight + headerHeight}px;
9`
translucent
with headerTransparent: true
1<StatusBar translucent barStyle="light-content" />
But this will give you issues with React Navigation if you use headerTransparent
true
for the default navigation header. You’ll have to manually add a margin top to avoid content flowing under the status bar
It appears that React Navigation default header doesn’t expect Android’s Status Bar to be translucent when you set headerTransparent
to be true
. When you do set headerTransparent: true
, you also have to set headerForceInset: { vertical: 'never' }
for it to not show any extra empty space, specially for nested headers.
1<StatusBar translucent={false} />
1// Translucent header, StatusBar should have translucent={false}
2headerTransparent: true,
3headerShown: true,
4headerForceInset: { vertical: 'never' }, // get rid of extra empty space at top
5headerStyle: { marginTop: Platform.OS === 'ios' ? Dimension.statusBarHeight : 0 },
1if (Platform.OS === 'android') {
2 // removes extra space at top of header on android
3 // SafeAreaView.setStatusBarHeight(0)
4}