Mobile Dev

Fix Android Navigation Bar Color in Expo: Black/Gray Issues

Learn how to consistently set Android navigation bar color in Expo using expo-navigation-bar. Fix black on Redmi, dim gray on OnePlus with app.json config, runtime API, and EAS Build for uniform results across devices.

1 answer 1 view

How to change the system navigation bar background color in Expo using expo-navigation-bar on Android? The color is not updating properly.

Tested the same APK on:

  • Redmi 9 Prime: Shows black
  • OnePlus Nord CE3: Shows dim gray

What configuration is needed to set the navigation bar color consistently across Android devices?

To fix inconsistent android navigation bar color issues in Expo—like black on Redmi 9 Prime or dim gray on OnePlus Nord CE3—configure the navigation bar android background via app.json with the expo-navigation-bar plugin and EAS Build for native consistency. Runtime changes with setBackgroundColorAsync often fail due to gesture navigation, edge-to-edge mode, or timing; disable edge-to-edge or set colors pre-build to ensure uniform results across devices. Test on physical hardware after rebuilding, as Expo Go ignores many native tweaks.


Contents


Understanding expo-navigation-bar on Android

Ever built an Expo app only to see the android bottom navigation bar looking wrong on different phones? You’re not alone. The expo-navigation-bar module gives you control over Android’s system navigation bar—the one with back, home, and recent apps buttons. But Android’s UI varies wildly by manufacturer. Xiaomi (Redmi) defaults to black in some modes, while OnePlus goes dim gray, especially with gestures enabled.

This isn’t a bug in your code. It’s how Android handles system UI. The Expo documentation explains that colors can differ because devices tweak the native bar for their themes. Want reliability? Skip runtime hacks for most cases and lock it in at build time.

Short version: Install expo-navigation-bar, tweak app.json, rebuild with EAS. Done.

What Controls the Bar?

Three main levers:

  • Runtime API: setBackgroundColorAsync(color)—quick but flaky.
  • app.json config: Native resources set before launch.
  • Device settings: Gestures or edge-to-edge override everything.

We’ll hit all three. But first, why yours failed.


Why Your Navigation Bar Android Color Isn’t Changing

Your APK shows black on Redmi 9 Prime, dim gray on OnePlus Nord CE3. Classic symptoms. Here’s the breakdown from real-world reports.

Gesture navigation kills custom colors. On OnePlus, swiping up instead of buttons? The bar turns transparent-ish, defaulting to gray. Expo’s system bars guide nails it: edge-to-edge mode (common on modern Android) makes the bar transparent, ignoring expo-navigation-bar entirely. System falls back to black (Redmi) or gray (OnePlus).

Timing matters too. Calling setBackgroundColorAsync too early—before the native module loads—flops silently. GitHub issues like #19887 show “transparent” turning gray. Another #36814 logs {"_j": "#00000000"} but no visual shift on Galaxy S10.

And Expo Go? Forget it. Those changes need a built APK.

Quick test: Does your android/app/src/main/res/values/colors.xml have navigationBarColor? If not, add it manually in bare workflow—or use plugins for managed.


Runtime Color Changes with setBackgroundColorAsync

For dynamic colors (say, dark/light mode), use the API. But wrap it safely.

javascript
import * as NavigationBar from 'expo-navigation-bar';

useEffect(() => {
 async function setNavColor() {
 // Wait for module readiness
 const currentColor = await NavigationBar.getBackgroundColorAsync();
 await NavigationBar.setBackgroundColorAsync('#0f172a'); // Your slate dark
 await NavigationBar.setButtonStyleAsync('light'); // Icons visible
 }
 setNavColor();
}, []);

Why the getBackgroundColorAsync first? Official docs warn: Call before the module’s ready, and it ignores you. On Redmi, this dodges black defaults.

But runtime won’t fix gestures. Users with edge-to-edge get system colors anyway. For apps needing consistency—like yours—build-time wins.

Pro tip: Pair with StatusBar for full immersion. expo-status-bar handles the top.


Build-Time Configuration for Consistent Colors

This is the fix for cross-device uniformity. Expo’s androidNavigationBar in app.json sets native XML before splash.

  1. Install: npx expo install expo-navigation-bar

  2. Update app.json (or app.config.js):

json
{
 "expo": {
 "plugins": [
 [
 "expo-navigation-bar",
 {
 "backgroundColor": "#0f172a",
 "barStyle": "light"
 }
 ]
 ],
 "androidNavigationBar": {
 "visible": "leanback",
 "barStyle": "light-content",
 "backgroundColor": "#0f172a"
 }
 }
}

backgroundColor must be 6-char hex—no rgba here, or it fails. App config docs confirm: EAS Build applies this to colors.xml, avoiding flash-of-wrong-color on launch.

  1. Build: eas build --platform android

  2. Install APK on Redmi/OnePlus. Boom—consistent android navigation bar color.

Stack Overflow confirms this merged in 2019. No more device roulette.


Device-Specific Fixes: Redmi Black, OnePlus Gray

Redmi 9 Prime (MIUI) loves black. Force via XML: Edit android/app/src/main/res/values/colors.xml:

xml
<resources>
 <color name="navigationBarColor">#0f172a</color>
</resources>

But managed workflow? Plugin does this automatically.

OnePlus Nord CE3: Gesture nav culprit. Users can’t disable easily, but Expo notes say API is ignored. Solution: Detect gestures (tricky) or stick to opaque mode.

Disable edge-to-edge in manifest (bare only):

xml
<activity android:windowLayoutInDisplayCutoutMode="shortEdges" />

For Expo: Set android:enableOnBackInvokedCallback="false" in plugins if needed. Test on emulators matching your devices—Android Studio’s got Redmi/OnePlus images.

What if still gray? OEM skins override. Native module hack: Window.setNavigationBarColor() via custom dev client. Overkill for most.


Troubleshooting and Best Practices

Stuck? Run this checklist.

  • Black/gray persists? Rebuild with EAS—no Expo Go.
  • Transparent fails? Use solid hex, not “transparent”.
  • Gestures? Inform users or design around (scrim overlay).
  • Logs: adb logcat | grep NavigationBar for clues.
  • Versions: Expo SDK 51+, expo-navigation-bar 1.7+.
  • Test matrix: Redmi (MIUI 12+), OnePlus (OxygenOS 13+), Pixel (stock).

Best practices:

  • Always build-time for launch color.
  • Runtime for themes.
  • Fallback: useColorScheme() + async checks.
  • Monitor Expo GitHub for OEM quirks.

Scale to prod? CI/CD with EAS ensures every build matches.

And yeah, it gets tricky with folds/flips, but basics covered.


Sources

  1. NavigationBar - Expo Documentation
  2. System bars - Expo Documentation
  3. app.json / app.config.js - Expo Documentation
  4. [expo-navigation-bar] You can’t set the NavBar background color to “transparent” · Issue #19887 · expo/expo
  5. expo-navigation-bar cannot work · Issue #36814 · expo/expo
  6. reactjs - Change navigation bar on android with RN with expo? - Stack Overflow

Conclusion

Lock in your android navigation bar color with app.json and EAS Build—it’s the reliable path past Redmi black and OnePlus gray headaches. Runtime tweaks shine for themes, but gestures/edge-to-edge demand native config. Rebuild, test on target devices, and you’ll ship a polished navigation bar android every time. Questions? Dive into those Expo docs links.

Authors
Verified by moderation
Moderation
Fix Android Navigation Bar Color in Expo: Black/Gray Issues