Learn how to support light and dark modes in your app.
Whether you are personally on team light or team dark, it's becoming increasingly common for apps to support these two color schemes. Here is an example of how supporting both modes looks in an Expo project:
Projects require additional configuration to support switching between light and dark modes for Android and iOS. However, no additional configuration is required for the web.
You can configure the supported appearance styles in app.json with the userInterfaceStyle
property. You can also configure specific platforms to support different appearance styles by setting either android.userInterfaceStyle
or ios.userInterfaceStyle
to the preferred value.
The available options are automatic
(follow system appearance settings and notify about any change user makes), light
(restrict the app to support light theme only), and dark
(restrict the app to support dark theme only). The app will default to the light style if this property is absent. Here is an example configuration:
{
"expo": {
"userInterfaceStyle": "automatic"
}
}
In development builds, you'll need to install the native package expo-system-ui
. Otherwise, the userInterfaceStyle
property is ignored. You can also use following command to check if the project is misconfigured:
npx expo config --type introspect
If the project is misconfigured, you'll see a warning as shown below:
» android: userInterfaceStyle: Install expo-system-ui in your project to enable this feature.
Appearance locking requires
react-native@0.63.3
to work correctly.
Ensure that the uiMode
flag is present on your MainActivity
(and any other activities where this behavior is desired) in AndroidManifest.xml:
<activity
...
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode">
Implement the onConfigurationChanged
method in MainActivity.java (react-native@0.63.3
don't need this):
import android.content.Intent; // <--- import
import android.content.res.Configuration; // <--- import
public class MainActivity extends ReactActivity {
......
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Intent intent = new Intent("onConfigurationChanged");
intent.putExtra("newConfig", newConfig);
sendBroadcast(intent);
}
......
}
You can configure supported styles with the UIUserInterfaceStyle key in your app Info.plist. Use Automatic
to support both light and dark modes.
To detect the color scheme in your project, use Appearance
and/or useColorScheme
from react-native
:
import { Appearance, useColorScheme } from 'react-native';
Then, you can use useColorScheme()
hook as shown below:
function MyComponent() {
let colorScheme = useColorScheme();
if (colorScheme === 'dark') {
// render some dark thing
} else {
// render some light thing
}
}
In some cases, you will find it helpful to get the current color scheme imperatively with Appearance.getColorScheme()
and/or listen to changes with Appearance.addChangeListener
.
Don't forget to configure your project to support the automatic color scheme as described above in Configuration.
Snack is locked to light mode.
import React from 'react';
import { Text, StyleSheet, View, useColorScheme } from 'react-native';
import { StatusBar } from 'expo-status-bar'; // automatically switches bar style based on theme!
export default function App() {
const colorScheme = useColorScheme();
const themeTextStyle = colorScheme === 'light' ? styles.lightThemeText : styles.darkThemeText;
const themeContainerStyle =
colorScheme === 'light' ? styles.lightContainer : styles.darkContainer;
return (
<View style={[styles.container, themeContainerStyle]}>
<Text style={[styles.text, themeTextStyle]}>Color scheme: {colorScheme}</Text>
<StatusBar />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
lightContainer: {
backgroundColor: '#d0d0c0',
},
darkContainer: {
backgroundColor: '#242c40',
},
lightThemeText: {
color: '#242c40',
},
darkThemeText: {
color: '#d0d0c0',
},
});
While you're developing your project, you can change your simulator's or device's appearance by using the following shortcuts:
adb shell "cmd uimode night yes"
to enable dark mode, and adb shell "cmd uimode night no"
to disable dark mode.