expo: "androidNavigationBar" ignored when Modal is visible

šŸ› Bug Report

Environment

Expo CLI 3.17.21 environment info:
    System:
      OS: macOS 10.15.4
      Shell: 5.7.1 - /bin/zsh
    Binaries:
      Node: 13.11.0 - /var/folders/wh/ctzdsw7n5j34k0xn6j71d4gh0000gn/T/yarn--1586550885404-0.2810176708311194/node
      Yarn: 1.22.4 - /var/folders/wh/ctzdsw7n5j34k0xn6j71d4gh0000gn/T/yarn--1586550885404-0.2810176708311194/yarn
      npm: 6.13.7 - /usr/local/bin/npm
    IDEs:
      Xcode: /undefined - /usr/bin/xcodebuild
    npmPackages:
      expo: ^37.0.7 => 37.0.7
      react: ^16.13.1 => 16.13.1
      react-native: https://github.com/expo/react-native/archive/sdk-37.0.0.tar.gz => 0.61.4
    npmGlobalPackages:
      expo-cli: 3.16.1

App targets: iOS and Android.

Steps to Reproduce

  1. Change the Android Navigation Bar color by adding the following to app.json:
"androidNavigationBar": {
  "barStyle": "dark-content",
  "backgroundColor": "#FFFFFF"
}

The Navigation Bar should now be white.

  1. Use a <Modal /> component somewhere in the app.

Expected Behavior

The Navigation Bar appearance should not change when using the <Modal /> component.

Actual Behavior

The Navigation Bar reverts to its default color when using the <Modal /> component.

Reproducible Demo

I wasn’t able to create a Snack since this requires changes to the app.json file. If needed, I can build a repro case in a standalone repository.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 15
  • Comments: 21 (5 by maintainers)

Most upvoted comments

I’m still experiencing this. It’s insane…

After 2 years later since this issue opened, and this bug is still exists. Is there any solution for this problem?

Also experiencing this issue, setBackgroundColorAsync from expo-navigation-bar doesn’t work with react-native’s Modal

why this issue is closed?

This is still an issue. However, for me the navigationbar color set in app.json (from grey) gets overwritten (to white) when a modal opens.

I am not using any third party libraries

Also experiencing this issue.

Still facing the same issue

3 years later… any solution for this issue?

Been bugging me for a few days, still an issue.

The ā€œsolutionā€ linked above doesn’t really fix the issue just changes it a bit. You can make any modification to the AndroidManifest.xml or styles.xml using expo config plugins.

Here is an example in TypeScript (will need to strip the types or do this):

import {
  ConfigPlugin,
  withAndroidStyles,
  XML,
  AndroidConfig,
} from "@expo/config-plugins";

const withFullScreenDialogStyles: ConfigPlugin = (config) => {
  return withAndroidStyles(config, async (config) => {
    config.modResults = await configureFullScreenDialog(config.modResults);
    return config;
  });
};

async function configureFullScreenDialog(
  styles: AndroidConfig.Resources.ResourceXML
): Promise<AndroidConfig.Resources.ResourceXML> {
  // Remove existing theme
  styles.resources.style = styles.resources.style!.filter(
    (style) => style.$.name !== "Theme.FullScreenDialog"
  );

  // 1A. You can build the XML object using the JS API
  const res = AndroidConfig.Resources.buildResourceGroup({
    parent: 'AppTheme',
    name: 'Theme.FullScreenDialog',
    items: [
      AndroidConfig.Resources.buildResourceItem({
        name: 'android:windowNoTitle',
        value: 'true'
      })
    ]
  })

  // 1B. You could build the XML object using the parser API
  const res = (
    await XML.parseXMLAsync(`<style name="Theme.FullScreenDialog" parent="AppTheme">
  <item name="android:windowNoTitle">true</item>
  <item name="android:windowIsFloating">false</item>
  <item name="android:windowBackground">@android:color/transparent</item>
  <item name="android:statusBarColor">@android:color/transparent</item>
  <item name="android:navigationBarColor">@android:color/transparent</item>
</style>`)
  ).style as AndroidConfig.Resources.ResourceGroupXML;

  // 2. Add the resource object to the styles to be written
  styles.resources.style.push(res);
  return styles;
}

module.exports = withFullScreenDialogStyles;

This can be tested in memory using expo config --type introspect or locally with expo prebuild -p android --no-install then check the styles.xml file.

Hopefully this helps someone! I don’t use expo, but I believe the issue starts with the React native modal trying to use the default color of navigationBarColor in the res/values/styles.xml file. So by setting it to transparent and then changing it programmatically, this should solve your issue. Full answer below.

I added an answer to something similar on stackoverflow https://stackoverflow.com/a/75046007/17172147

This is the answer below. I did not test it on the status bar, but maybe you could try using ā€œandroid:statusBarColorā€ and also setting it to @android:color/transparent as well. Good luck!


I had this problem in Android as well. What I believe is happening is the react-native modal is simply taking the default android:navigationBarColor in the styles.xml and so every time it pops up, it overwrites the current navigation bar color until it gets dismissed.

The flag statusBarTranslucent did not work for me.

I was able to fix this by navigating to res/values/styles.xml

Then in the AppTheme style I added navigationBarColor to be transparent. It looks like this

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:textColor">@android:color/black</item>
    <item name="android:navigationBarColor">@android:color/transparent</item> // <----This is what I added
  </style>

Then in my react native code, I used react-native-navigation-bar-color. I believe this should work with expo-navigation-bar since the main issue is derived from react native modal trying to overlay the default navBarColor value.

import changeNavigationBarColor from "react-native-navigation-bar-color";

  const setDarkMode = (isDarkMode: boolean) => {
    // logic to change my app's themeProvider to dark mode
    changeNavigationBarColor(isDarkMode ? "black" : "white"); // Then I change the navigation bar color.
  };