laneboyandrew
laneboyandrew

Reputation: 333

React Native Expo. Android dark mode issue

When I change my mobile theme from light to dark it is affecting the background color of my react native app. I just want it to always remain white but it changes white to black when I change my mobile theme from light to dark. I have found a solution for React Native without Expo: React native android dark mode issue but I cannot use it because I don't have Android folder.

Upvotes: 4

Views: 10072

Answers (2)

Deywerson Pereira
Deywerson Pereira

Reputation: 158

I was facing the same issue until today and after reading a lot of documents I have found this:

https://docs.expo.dev/guides/color-schemes/

On your app.json file:

{
  "expo": {
    "userInterfaceStyle": "light",
    "ios": {
      "userInterfaceStyle": "light"
    },
    "android": {
      "userInterfaceStyle": "light"
    }
  }
}

after this, don't forget to install expo-system-ui. To check if all is okay, you can run expo config --type introspect or npx expo config --type introspect for SKD 45+.

But this wont fix the problem with Xiaomi devices. To solve for this devices we need a plus config, shown below:

  • create a folder in your root directory (same directory than app.json) named plugin;

  • add a file named withDisableForcedDarkModeAndroid.js

  • add this code at this new file:

const {
    createRunOncePlugin,
    withAndroidStyles,
    AndroidConfig
} = require('@expo/config-plugins');

function setForceDarkModeToFalse(styles) {
    styles = AndroidConfig.Styles.assignStylesValue(styles, {
        add: true,
        parent: AndroidConfig.Styles.getAppThemeLightNoActionBarGroup(),
        name: `android:forceDarkAllowed`,
        value: "false",
    });

    return styles;
}

const withDisableForcedDarkModeAndroid = (config) => {
    return withAndroidStyles(config, (config) => {
        config.modResults = setForceDarkModeToFalse(config.modResults);
        return config;
    });
};

module.exports = createRunOncePlugin(withDisableForcedDarkModeAndroid, 'disable-forced-dark-mode', '1.0.0');

After this, add the new plugin at app.json file, under expo.config.plugin:

{
  "expo": {
      [...]
    "userInterfaceStyle": "light",
    "ios": {
      [...]
      "userInterfaceStyle": "light",
    },
    "android": {
      [...]
      "userInterfaceStyle": "light",
    },
    "plugins": [
      [
        "./plugins/withDisableForcedDarkModeAndroid.js",
        {}
      ]
    ]
  }
}

That's it! Worked here :D I found this code here: https://gist.github.com/hirbod/d6bb5d0fc946a12ba9e3cf01120c604a

Thx in advance for the author!

PS.1: userInterfaceStyle - The available options are: automatic (follow system appearance settings and notify about any change user makes), light (restrict app to support light theme only), and dark (restrict app to support dark theme only).

PS.2: This specific configuration for Xiaomi devices is necessary because of the android:forceDarkAllowed=true configuration that these devices have. This configuration is not overwritten just by adding the configurations proposed by the Expo team.

Upvotes: 14

Rakesh Medpalli
Rakesh Medpalli

Reputation: 474

Add "userInterfaceStyle" : "light" in app.json / app.config.js

light (restrict app to support light theme only)

If this key is absent, the app will default to the light style.

Example app.json configuration:

{
  "expo": {
    "userInterfaceStyle": "automatic",
    "ios": {
      "userInterfaceStyle": "dark"
    },
    "android": {
      "userInterfaceStyle": "light"
    }
  }
}

[Expo Reference Link][1]

or using Appearance

  • expo install react-native-appearance

Example -

import React from 'react';
import { Text, SafeAreaView, StatusBar, StyleSheet } from 'react-native';
import { AppearanceProvider, useColorScheme } from 'react-native-appearance';

export default function AppContainer() {
  return (
    <AppearanceProvider>
      <App />
    </AppearanceProvider>
  );
}

function App() {
  const colorScheme = useColorScheme();

  const themeStatusBarStyle = colorScheme === 'light' ? 'dark-content' : 'light-content';
  const themeTextStyle = colorScheme === 'light' ? styles.lightThemeText : styles.darkThemeText;
  const themeContainerStyle =
    colorScheme === 'light' ? styles.lightContainer : styles.darkContainer;

  return (
    <SafeAreaView style={[styles.container, themeContainerStyle]}>
      <StatusBar barStyle={themeStatusBarStyle} />
      <Text style={[styles.text, themeTextStyle]}>Color scheme: {colorScheme}</Text>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  lightContainer: {
    backgroundColor: '#D0D0C0',
  },
  darkContainer: {
    backgroundColor: '#242C40',
  },
  lightThemeText: {
    color: '#242C40',
  },
  darkThemeText: {
    color: '#D0D0C0',
  },
});

Upvotes: 1

Related Questions