108

Is there a single place in the react native iOS native code that I could modify to set iOS statusbar backgroundColor? RCTRootView.m ?

The react native StatusBar component only support backgroundColor for Android only.

The iOS operating system seems to allow setting status bar backgroundColor

My goal is to have a darker status bar color. Example

Rudolf Adamkovič
  • 31,030
  • 13
  • 103
  • 118
Ed of the Mountain
  • 5,219
  • 4
  • 46
  • 54
  • is there a way to get the source code for having a taskbar with this buttons please ( menu, search etc )? thanks – AlainIb Jul 24 '17 at 07:53
  • https://github.com/oblador/react-native-vector-icons includes all of the Google Material Design Icons found at https://material.io/icons/ plus many other icons you may browse here: https://oblador.github.io/react-native-vector-icons/ – Ed of the Mountain Aug 24 '17 at 17:27

13 Answers13

280

iOS doesn't have a concept of a status bar bg. Here's how you'd achieve this in a cross-platform way:

import React, {
  Component,
} from 'react';
import {
  AppRegistry,
  StyleSheet,
  View,
  StatusBar,
  Platform,
  SafeAreaView
} from 'react-native';

const MyStatusBar = ({backgroundColor, ...props}) => (
  <View style={[styles.statusBar, { backgroundColor }]}>
    <SafeAreaView>
      <StatusBar translucent backgroundColor={backgroundColor} {...props} />
    </SafeAreaView>
  </View>
);

class DarkTheme extends Component {
  render() {
    return (
      <View style={styles.container}>
        <MyStatusBar backgroundColor="#5E8D48" barStyle="light-content" />
        <View style={styles.appBar} />
        <View style={styles.content} />
      </View>
    );
  }
}

const STATUSBAR_HEIGHT = StatusBar.currentHeight;
const APPBAR_HEIGHT = Platform.OS === 'ios' ? 44 : 56;

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  statusBar: {
    height: STATUSBAR_HEIGHT,
  },
  appBar: {
    backgroundColor:'#79B45D',
    height: APPBAR_HEIGHT,
  },
  content: {
    flex: 1,
    backgroundColor: '#33373B',
  },
});

AppRegistry.registerComponent('App', () => DarkTheme);

simulator

Maybe it's not clear in the code, but the trick is to use StatusBar, which works for Android, and create a "fake" status bar (a View with backgroundColor) for IOS.

Vencovsky
  • 28,550
  • 17
  • 109
  • 176
jmurzy
  • 3,816
  • 1
  • 17
  • 11
  • 18
    Wow! I just tested on both Android and iOS. Perfect! That is an excellent cross platform solution that works out-of-the-box! Thank you very much for taking time to post this. I expect this will help many developers. – Ed of the Mountain Sep 02 '16 at 22:04
  • I tried a similar fix using the `` component for the rest of the navbar, but couldn't get it working (tried a top border & inserting another component inside it). Any ideas? – Brad Adams Oct 26 '16 at 21:23
  • 2
    Doesn't this only work if your content isn't taller than the screen size? If you have to scroll the status bar background gets hidden. – SomethingOn Jan 11 '17 at 22:33
  • 1
    @sowmya Updated the solution to add support for newer versions of Android. – jmurzy Aug 02 '17 at 02:58
  • @jmurzy not sure why I have a gradient bg colour on my status bar...any idea how to remove it? i want it like your example, flat... – ComeRun Oct 30 '17 at 03:49
  • @jmurzy update: gradients only happens on iOS ... ugly! can it be removed? – ComeRun Oct 30 '17 at 04:36
  • This looks great, except it works weird for iPhoneX. its height is 45 so need conditionally check it as well. For example, with this helper https://www.npmjs.com/package/react-native-iphone-x-helper or `Expo.Constants.statusBarHeight` – jamland Mar 12 '18 at 11:05
  • Hi guys, I couldn't get this to work. backgroundColor is not working, any ideas ! – Yasir May 13 '18 at 14:56
  • Thanks! I've been struggling for a solution. Worked perfectly for me on iOS 11.4.1. – Bob Cardenas Sep 15 '18 at 18:04
  • Verified on iOS with React Native 0.59 :) – Alex Aug 15 '19 at 18:10
  • @jmurzy What's the purpose of the AppBar? – gkeenley Apr 21 '20 at 18:53
  • 2
    This is a good solution, but how to achieve this for iphones having notch.?? – sanjeev shetty Aug 09 '20 at 19:15
75

Add import { StatusBar } from 'react-native'; to the top of your app.js and then add StatusBar.setBarStyle('light-content', true); as the first line in your render() to change the status bar text/icons to white.

The other color options are 'default' and 'dark-content'.

Refer to https://facebook.github.io/react-native/docs/statusbar.html for further info.

Other than that: no, you would have to follow the link you provided.

Jim Bergman
  • 5,207
  • 2
  • 17
  • 19
dv3
  • 4,369
  • 5
  • 28
  • 50
  • Ideally, where would one put that call to StatusBar.setBarStyle()? I tried putting it in render() and in componentWillMount of my root component but it crashed Xcode hard... Is there another spot that would be a good candidate in which to put this call? Thanks! – Evan K. Stone Nov 18 '16 at 00:41
  • OK - I think I may have fixed it. There were two other issues I didn't mention: 1) I'm using a NavigatorIOS with the StatusBar (most of the examples I've seen use a generic Navigator), and 2) I'm testing **on device** with Release configuration. So... to solve it, I took the call out of the root component and moved it to the component used by the NavigatorIOS's initialRoute (let's call it ToDoList). Inside ToDoList's componentDidMount, I added the call to StatusBar.setBarStyle('light-content', false) and it worked! – Evan K. Stone Nov 18 '16 at 00:54
  • In a functional component that doesn't use render(), put it in your App() function. If your app is light and you want a dark text in status bar, use `{'dark-content', true}` – Raphael Pinel Feb 01 '21 at 09:19
15

you need to customize it.
StatusBar is not part of screen layout in ios else if you use SafeAreaView from reac-native

instead use react-native-safe-area-context and customize it.

see this snack.

enter image description here

Ahmed Gaber
  • 3,384
  • 2
  • 12
  • 18
9

This works for me with react-native-safe-area-context version 3.3.2

import { StatusBar } from "react-native"
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context"

const App = () => {

  const theme = ... get your theme

  return (
    <>
      <StatusBar
        backgroundColor={theme === "light" ? "#fff" : "#000"}
        barStyle={theme === "light" ? "dark-content" : "light-content"}
      />
      <SafeAreaProvider>
        <SafeAreaView
          style={{
            flex: 1,
            backgroundColor: theme === "light" ? "#fff" : "#000",
          }}
        >  

          // stuff goes here

        </SafeAreaView>
      </SafeAreaProvider>
    </>
  )
}
JTan
  • 149
  • 1
  • 5
7

set iOS & Android statusbar backgroundColor in react-native

    import React, { Component } from 'react';
    import { Platform, StyleSheet, View, StatusBar } from 'react-native';
    import Constants from 'expo-constants';


    class Statusbar extends Component {

        render() {
            return (
                <View style={styles.StatusBar}>
                    <StatusBar translucent barStyle="light-content" />
                </View>
            );
        }
    }

    const styles = StyleSheet.create({
        StatusBar: {
            height: Constants.statusBarHeight,
            backgroundColor: 'rgba(22,7,92,1)'
        }
    });

    export default Statusbar;
Talha Javed
  • 87
  • 1
  • 6
6

If you are using react-native-navigation, you need to:

1-) Add this to your info.plist file:

<key>UIViewControllerBasedStatusBarAppearance</key>
<string>YES</string>

2-) At first line of your render() function, eg:

  render(){
    this.props.navigator.setStyle({
      statusBarTextColorScheme: 'light'
    });
    return (
      <Login navigator={this.props.navigator}></Login>
    );
  }

This example will transform your status bar to light text/buttons/icons color. enter image description here

toel
  • 155
  • 2
  • 15
  • 1
    The code you’ve posted only sets the text theme of the status bar to light. How did you achieve the same background as the content? – Ash Apr 16 '19 at 23:18
  • @Ash i assume that if the header is background red automatically the status bar will be red because the header will be positioned behind the statusbar – cristian camilo cedeño gallego Nov 12 '19 at 02:34
  • 1
    ExceptionsManager.js:179 RCTStatusBarManager module requires that the UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO – glinda93 Jan 17 '21 at 14:47
4

Add to root view. (Out of SafeAreaView if has)

{Platform.OS === 'ios' &&
 <View style={{
     width: "100%",
     height: 100, // For all devices, even X, XS Max
     position: 'absolute',
     top: 0,
     left: 0,
     backgroundColor: "red"}}
/>}
// App screen
...
oolionoo
  • 113
  • 11
1

Please, make sure to use padding and not margin. This is my code and it works well in iOS:

import { SafeAreaView } from 'react-native'
import { StatusBar } from 'expo-status-bar'
// ...
// ...
return <SafeAreaView style={{ paddingTop: height }}>
  {/* your content here */}
  <StatusBar style="light" />
</SafeAreaView>
Cequiel
  • 3,505
  • 6
  • 27
  • 44
0
import {SafeAreaConsumer} from 'react-native-safe-area-context';

<SafeAreaConsumer>
{(insets)=>(
<View style={{flex:1}}>
<View style={{height:insets.top ,backgroundColor :"black"}}/>
<StatusBar barStyle="light-content"/>
<View style={{flex:1}}>
  <Text>My Text</Text>
</View>
</View>
)}
</SafeAreaConsumer>
mohit arora
  • 592
  • 6
  • 10
0

I was able to change the background color of status bar on iOS but updating the backgroundColor property of the SafeAreaView component.

<SafeAreaView style={{backgroundColor: 'blue'}}>
   // App Content
</SafeAreaView>
Murtuza
  • 308
  • 2
  • 14
0

Slightly changed jmurzy's solution this one should work with android and iOS including iOS with notch:

import React from 'react'
import { SafeAreaView, StatusBar, View } from 'react-native'
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'

const App = () => {
    const isDarkMode = true
    return (
        <SafeAreaProvider>
            <CustomStatusBar
                barStyle={isDarkMode ? 'light-content' : 'dark-content'}
                backgroundColor={'red'}
            />
            <SafeAreaView style={{ flex: 1 }}>

                
            </SafeAreaView>
        </SafeAreaProvider>
    )
}

export default App

const CustomStatusBar = ({backgroundColor, ...props}) => {
    const { top } = useSafeAreaInsets()

    return (
        <View style={{ height: (StatusBar.currentHeight || top), backgroundColor }}>
            <SafeAreaView style={{ backgroundColor }}>
                <StatusBar translucent backgroundColor={backgroundColor} {...props} />
            </SafeAreaView>
        </View>
    )
}
nodir.dev
  • 414
  • 4
  • 5
0

If you are using React Navigation it is really easy!

Just set the headerStyle, see also documentation here.

Something like

<Stack.Navigator initialRouteName="Home">
  <Stack.Screen
    name="Home"
    component={HomeScreen}
    options={{
      title: 'my app',
      headerStyle: {
        backgroundColor: 'green',
      },
    }}
  />
</Stack.Navigator>
Gianluca Casati
  • 3,303
  • 1
  • 32
  • 20
0

It is enough for you to just use the SafeAreaView element but close it right after the header and additionally enclose your page in a simple view element. This will allow you to just set the backgroundColor of the SafeAreaView, thus getting the desired result.

Luka
  • 1
  • This duplicates other answers; other users have discussed `SafeAreaView` in much more detail than you have so far. Please don't post an answer unless you have something new to contribute. You can show your support for an original answer by upvoting. – Ben A. Aug 29 '23 at 00:02